/* * Copyright 2016 Elvis Hew * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.elvishew.xlog; import com.elvishew.xlog.formatter.border.BorderFormatter; import com.elvishew.xlog.formatter.message.json.JsonFormatter; import com.elvishew.xlog.formatter.message.object.ObjectFormatter; import com.elvishew.xlog.formatter.message.throwable.ThrowableFormatter; import com.elvishew.xlog.formatter.message.xml.XmlFormatter; import com.elvishew.xlog.formatter.stacktrace.StackTraceFormatter; import com.elvishew.xlog.formatter.thread.ThreadFormatter; import com.elvishew.xlog.interceptor.Interceptor; import com.elvishew.xlog.internal.DefaultsFactory; import com.elvishew.xlog.internal.SystemCompat; import com.elvishew.xlog.internal.util.StackTraceUtil; import com.elvishew.xlog.printer.Printer; import com.elvishew.xlog.printer.PrinterSet; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; /** * A logger is used to do the real logging work, can use multiple log printers to print the log. * <p> * A {@link Logger} is always generated and mostly accessed by {@link XLog}, but for customization * purpose, you can configure a {@link Logger} via the {@link Builder} which is returned by * {@link XLog} when you trying to start a customization using {@link XLog#tag(String)} * or other configuration method, and to use the customized {@link Logger}, you should call * the {@link Builder#build()} to build a {@link Logger}, and then you can log using * the {@link Logger} assuming that you are using the {@link XLog} directly. */ public class Logger { /** * The log configuration which you should respect to when logging. */ private LogConfiguration logConfiguration; /** * The log printer used to print the logs. */ private Printer printer; /** * Construct a logger. * * @param logConfiguration the log configuration which you should respect to when logging * @param printer the log printer used to print the log */ /*package*/ Logger(LogConfiguration logConfiguration, Printer printer) { this.logConfiguration = logConfiguration; this.printer = printer; } /** * Construct a logger using builder. * * @param builder the logger builder */ /*package*/ Logger(Builder builder) { LogConfiguration.Builder logConfigBuilder = new LogConfiguration.Builder( XLog.sLogConfiguration); if (builder.logLevel != 0) { logConfigBuilder.logLevel(builder.logLevel); } if (builder.tag != null) { logConfigBuilder.tag(builder.tag); } if (builder.threadSet) { if (builder.withThread) { logConfigBuilder.t(); } else { logConfigBuilder.nt(); } } if (builder.stackTraceSet) { if (builder.withStackTrace) { logConfigBuilder.st(builder.stackTraceOrigin, builder.stackTraceDepth); } else { logConfigBuilder.nst(); } } if (builder.borderSet) { if (builder.withBorder) { logConfigBuilder.b(); } else { logConfigBuilder.nb(); } } if (builder.jsonFormatter != null) { logConfigBuilder.jsonFormatter(builder.jsonFormatter); } if (builder.xmlFormatter != null) { logConfigBuilder.xmlFormatter(builder.xmlFormatter); } if (builder.throwableFormatter != null) { logConfigBuilder.throwableFormatter(builder.throwableFormatter); } if (builder.threadFormatter != null) { logConfigBuilder.threadFormatter(builder.threadFormatter); } if (builder.stackTraceFormatter != null) { logConfigBuilder.stackTraceFormatter(builder.stackTraceFormatter); } if (builder.borderFormatter != null) { logConfigBuilder.borderFormatter(builder.borderFormatter); } if (builder.objectFormatters != null) { logConfigBuilder.objectFormatters(builder.objectFormatters); } if (builder.interceptors != null) { logConfigBuilder.interceptors(builder.interceptors); } logConfiguration = logConfigBuilder.build(); if (builder.printer != null) { printer = builder.printer; } else { printer = XLog.sPrinter; } } /** * Log an object with level {@link LogLevel#VERBOSE}. * * @param object the object to log * @see Builder#addObjectFormatter(Class, ObjectFormatter) * @since 1.1.0 */ public void v(Object object) { println(LogLevel.VERBOSE, object); } /** * Log an array with level {@link LogLevel#VERBOSE}. * * @param array the array to log */ public void v(Object[] array) { println(LogLevel.VERBOSE, array); } /** * Log a message with level {@link LogLevel#VERBOSE}. * * @param format the format of the message to log * @param args the arguments of the message to log */ public void v(String format, Object... args) { println(LogLevel.VERBOSE, format, args); } /** * Log a message with level {@link LogLevel#VERBOSE}. * * @param msg the message to log */ public void v(String msg) { println(LogLevel.VERBOSE, msg); } /** * Log a message and a throwable with level {@link LogLevel#VERBOSE}. * * @param msg the message to log * @param tr the throwable to be log */ public void v(String msg, Throwable tr) { println(LogLevel.VERBOSE, msg, tr); } /** * Log an object with level {@link LogLevel#DEBUG}. * * @param object the object to log * @see Builder#addObjectFormatter(Class, ObjectFormatter) * @since 1.1.0 */ public void d(Object object) { println(LogLevel.DEBUG, object); } /** * Log an array with level {@link LogLevel#DEBUG}. * * @param array the array to log */ public void d(Object[] array) { println(LogLevel.DEBUG, array); } /** * Log a message with level {@link LogLevel#DEBUG}. * * @param format the format of the message to log, null if just need to concat arguments * @param args the arguments of the message to log */ public void d(String format, Object... args) { println(LogLevel.DEBUG, format, args); } /** * Log a message with level {@link LogLevel#DEBUG}. * * @param msg the message to log */ public void d(String msg) { println(LogLevel.DEBUG, msg); } /** * Log a message and a throwable with level {@link LogLevel#DEBUG}. * * @param msg the message to log * @param tr the throwable to be log */ public void d(String msg, Throwable tr) { println(LogLevel.DEBUG, msg, tr); } /** * Log an object with level {@link LogLevel#INFO}. * * @param object the object to log * @see Builder#addObjectFormatter(Class, ObjectFormatter) * @since 1.1.0 */ public void i(Object object) { println(LogLevel.INFO, object); } /** * Log an array with level {@link LogLevel#INFO}. * * @param array the array to log */ public void i(Object[] array) { println(LogLevel.INFO, array); } /** * Log a message with level {@link LogLevel#INFO}. * * @param format the format of the message to log, null if just need to concat arguments * @param args the arguments of the message to log */ public void i(String format, Object... args) { println(LogLevel.INFO, format, args); } /** * Log a message with level {@link LogLevel#INFO}. * * @param msg the message to log */ public void i(String msg) { println(LogLevel.INFO, msg); } /** * Log a message and a throwable with level {@link LogLevel#INFO}. * * @param msg the message to log * @param tr the throwable to be log */ public void i(String msg, Throwable tr) { println(LogLevel.INFO, msg, tr); } /** * Log an object with level {@link LogLevel#WARN}. * * @param object the object to log * @see Builder#addObjectFormatter(Class, ObjectFormatter) * @since 1.1.0 */ public void w(Object object) { println(LogLevel.WARN, object); } /** * Log an array with level {@link LogLevel#WARN}. * * @param array the array to log */ public void w(Object[] array) { println(LogLevel.WARN, array); } /** * Log a message with level {@link LogLevel#WARN}. * * @param format the format of the message to log, null if just need to concat arguments * @param args the arguments of the message to log */ public void w(String format, Object... args) { println(LogLevel.WARN, format, args); } /** * Log a message with level {@link LogLevel#WARN}. * * @param msg the message to log */ public void w(String msg) { println(LogLevel.WARN, msg); } /** * Log a message and a throwable with level {@link LogLevel#WARN}. * * @param msg the message to log * @param tr the throwable to be log */ public void w(String msg, Throwable tr) { println(LogLevel.WARN, msg, tr); } /** * Log an object with level {@link LogLevel#ERROR}. * * @param object the object to log * @see Builder#addObjectFormatter(Class, ObjectFormatter) * @since 1.1.0 */ public void e(Object object) { println(LogLevel.ERROR, object); } /** * Log an array with level {@link LogLevel#ERROR}. * * @param array the array to log */ public void e(Object[] array) { println(LogLevel.ERROR, array); } /** * Log a message with level {@link LogLevel#ERROR}. * * @param format the format of the message to log, null if just need to concat arguments * @param args the arguments of the message to log */ public void e(String format, Object... args) { println(LogLevel.ERROR, format, args); } /** * Log a message with level {@link LogLevel#ERROR}. * * @param msg the message to log */ public void e(String msg) { println(LogLevel.ERROR, msg); } /** * Log a message and a throwable with level {@link LogLevel#ERROR}. * * @param msg the message to log * @param tr the throwable to be log */ public void e(String msg, Throwable tr) { println(LogLevel.ERROR, msg, tr); } /** * Log an object with specific log level. * * @param logLevel the specific log level * @param object the object to log * @see Builder#addObjectFormatter(Class, ObjectFormatter) * @since 1.4.0 */ public void log(int logLevel, Object object) { println(logLevel, object); } /** * Log an array with specific log level. * * @param logLevel the specific log level * @param array the array to log * @since 1.4.0 */ public void log(int logLevel, Object[] array) { println(logLevel, array); } /** * Log a message with specific log level. * * @param logLevel the specific log level * @param format the format of the message to log, null if just need to concat arguments * @param args the arguments of the message to log * @since 1.4.0 */ public void log(int logLevel, String format, Object... args) { println(logLevel, format, args); } /** * Log a message with specific log level. * * @param logLevel the specific log level * @param msg the message to log * @since 1.4.0 */ public void log(int logLevel, String msg) { println(logLevel, msg); } /** * Log a message and a throwable with specific log level. * * @param logLevel the specific log level * @param msg the message to log * @param tr the throwable to be log * @since 1.4.0 */ public void log(int logLevel, String msg, Throwable tr) { println(logLevel, msg, tr); } /** * Log a JSON string, with level {@link LogLevel#DEBUG} by default. * * @param json the JSON string to log */ public void json(String json) { if (LogLevel.DEBUG < logConfiguration.logLevel) { return; } printlnInternal(LogLevel.DEBUG, logConfiguration.jsonFormatter.format(json)); } /** * Log a XML string, with level {@link LogLevel#DEBUG} by default. * * @param xml the XML string to log */ public void xml(String xml) { if (LogLevel.DEBUG < logConfiguration.logLevel) { return; } printlnInternal(LogLevel.DEBUG, logConfiguration.xmlFormatter.format(xml)); } /** * Print an object in a new line. * * @param logLevel the log level of the printing object * @param object the object to print */ private <T> void println(int logLevel, T object) { if (logLevel < logConfiguration.logLevel) { return; } String objectString; if (object != null) { ObjectFormatter<? super T> objectFormatter = logConfiguration.getObjectFormatter(object); if (objectFormatter != null) { objectString = objectFormatter.format(object); } else { objectString = object.toString(); } } else { objectString = "null"; } printlnInternal(logLevel, objectString); } /** * Print an array in a new line. * * @param logLevel the log level of the printing array * @param array the array to print */ private void println(int logLevel, Object[] array) { if (logLevel < logConfiguration.logLevel) { return; } printlnInternal(logLevel, Arrays.deepToString(array)); } /** * Print a log in a new line. * * @param logLevel the log level of the printing log * @param format the format of the printing log, null if just need to concat arguments * @param args the arguments of the printing log */ private void println(int logLevel, String format, Object... args) { if (logLevel < logConfiguration.logLevel) { return; } printlnInternal(logLevel, formatArgs(format, args)); } /** * Print a log in a new line. * * @param logLevel the log level of the printing log * @param msg the message you would like to log */ /*package*/ void println(int logLevel, String msg) { if (logLevel < logConfiguration.logLevel) { return; } printlnInternal(logLevel, msg); } /** * Print a log in a new line. * * @param logLevel the log level of the printing log * @param msg the message you would like to log * @param tr a throwable object to log */ private void println(int logLevel, String msg, Throwable tr) { if (logLevel < logConfiguration.logLevel) { return; } printlnInternal(logLevel, ((msg == null || msg.length() == 0) ? "" : (msg + SystemCompat.lineSeparator)) + logConfiguration.throwableFormatter.format(tr)); } /** * Print a log in a new line internally. * * @param logLevel the log level of the printing log * @param msg the message you would like to log */ private void printlnInternal(int logLevel, String msg) { String tag = logConfiguration.tag; String thread = logConfiguration.withThread ? logConfiguration.threadFormatter.format(Thread.currentThread()) : null; String stackTrace = logConfiguration.withStackTrace ? logConfiguration.stackTraceFormatter.format( StackTraceUtil.getCroppedRealStackTrack(new Throwable().getStackTrace(), logConfiguration.stackTraceOrigin, logConfiguration.stackTraceDepth)) : null; if (logConfiguration.interceptors != null) { LogItem log = new LogItem(logLevel, tag, thread, stackTrace, msg); for (Interceptor interceptor : logConfiguration.interceptors) { log = interceptor.intercept(log); if (log == null) { // Log is eaten, don't print this log. return; } // Check if the log still healthy. if (log.tag == null || log.msg == null) { throw new IllegalStateException("Interceptor " + interceptor + " should not remove the tag or message of a log," + " if you don't want to print this log," + " just return a null when intercept."); } } // Use fields after interception. logLevel = log.level; tag = log.tag; thread = log.threadInfo; stackTrace = log.stackTraceInfo; msg = log.msg; } printer.println(logLevel, tag, logConfiguration.withBorder ? logConfiguration.borderFormatter.format(new String[]{thread, stackTrace, msg}) : ((thread != null ? (thread + SystemCompat.lineSeparator) : "") + (stackTrace != null ? (stackTrace + SystemCompat.lineSeparator) : "") + msg)); } /** * Format a string with arguments. * * @param format the format string, null if just to concat the arguments * @param args the arguments * @return the formatted string */ private String formatArgs(String format, Object... args) { if (format != null) { return String.format(format, args); } else { StringBuilder sb = new StringBuilder(); for (int i = 0, N = args.length; i < N; i++) { if (i != 0) { sb.append(", "); } sb.append(args[i]); } return sb.toString(); } } /** * Builder for {@link Logger}. */ public static class Builder { /** * The log level, the logs below of which would not be printed. */ private int logLevel; /** * The tag string when {@link Logger} log. */ private String tag; /** * Whether we should log with thread info. */ private boolean withThread; /** * Whether we have enabled/disabled thread info. */ private boolean threadSet; /** * Whether we should log with stack trace. */ private boolean withStackTrace; /** * The origin of stack trace elements from which we should NOT log when logging with stack trace, * it can be a package name like "com.elvishew.xlog", a class name like "com.yourdomain.logWrapper", * or something else between package name and class name, like "com.yourdomain.". * <p> * It is mostly used when you are using a logger wrapper. */ private String stackTraceOrigin; /** * The number of stack trace elements we should log when logging with stack trace, * 0 if no limitation. */ private int stackTraceDepth; /** * Whether we have enabled/disabled stack trace. */ private boolean stackTraceSet; /** * Whether we should log with border. */ private boolean withBorder; /** * Whether we have enabled/disabled border. */ private boolean borderSet; /** * The JSON formatter when {@link Logger} log a JSON string. */ private JsonFormatter jsonFormatter; /** * The XML formatter when {@link Logger} log a XML string. */ private XmlFormatter xmlFormatter; /** * The throwable formatter when {@link Logger} log a message with throwable. */ private ThrowableFormatter throwableFormatter; /** * The thread formatter when {@link Logger} logging. */ private ThreadFormatter threadFormatter; /** * The stack trace formatter when {@link Logger} logging. */ private StackTraceFormatter stackTraceFormatter; /** * The border formatter when {@link Logger} logging. */ private BorderFormatter borderFormatter; /** * The object formatters, used when {@link Logger} logging an object. */ private Map<Class<?>, ObjectFormatter<?>> objectFormatters; /** * The intercepts, used when {@link Logger} logging. */ private List<Interceptor> interceptors; /** * The printer used to print the log when {@link Logger} log. */ private Printer printer; /** * Construct a builder, which will perform the same as the global one by default. */ public Builder() { XLog.assertInitialization(); } /** * Set the log level, the logs below of which would not be printed. * * @param logLevel the log level * @return the builder * @since 1.3.0 */ public Builder logLevel(int logLevel) { this.logLevel = logLevel; return this; } /** * Set the tag string when {@link Logger} log. * * @param tag the tag string when {@link Logger} log * @return the builder */ public Builder tag(String tag) { this.tag = tag; return this; } /** * Enable thread info. * * @return the builder */ public Builder t() { this.withThread = true; this.threadSet = true; return this; } /** * Disable thread info. * * @return the builder */ public Builder nt() { this.withThread = false; this.threadSet = true; return this; } /** * Enable stack trace. * * @param depth the number of stack trace elements we should log, 0 if no limitation * @return the builder */ public Builder st(int depth) { this.withStackTrace = true; this.stackTraceDepth = depth; this.stackTraceSet = true; return this; } /** * Enable stack trace. * * @param stackTraceOrigin the origin of stack trace elements from which we should NOT log when * logging with stack trace, it can be a package name like * "com.elvishew.xlog", a class name like "com.yourdomain.logWrapper", * or something else between package name and class name, like "com.yourdomain.". * It is mostly used when you are using a logger wrapper * @param depth the number of stack trace elements we should log, 0 if no limitation * @return the builder * @since 1.4.0 */ public Builder st(String stackTraceOrigin, int depth) { this.withStackTrace = true; this.stackTraceOrigin = stackTraceOrigin; this.stackTraceDepth = depth; this.stackTraceSet = true; return this; } /** * Disable stack trace. * * @return the builder */ public Builder nst() { this.withStackTrace = false; this.stackTraceOrigin = null; this.stackTraceDepth = 0; this.stackTraceSet = true; return this; } /** * Enable border. * * @return the builder */ public Builder b() { this.withBorder = true; this.borderSet = true; return this; } /** * Disable border. * * @return the builder */ public Builder nb() { this.withBorder = false; this.borderSet = true; return this; } /** * Set the JSON formatter when {@link Logger} log a JSON string. * * @param jsonFormatter the JSON formatter when {@link Logger} log a JSON string * @return the builder */ public Builder jsonFormatter(JsonFormatter jsonFormatter) { this.jsonFormatter = jsonFormatter; return this; } /** * Set the XML formatter when {@link Logger} log a XML string. * * @param xmlFormatter the XML formatter when {@link Logger} log a XML string * @return the builder */ public Builder xmlFormatter(XmlFormatter xmlFormatter) { this.xmlFormatter = xmlFormatter; return this; } /** * Set the throwable formatter when {@link Logger} log a message with throwable. * * @param throwableFormatter the throwable formatter when {@link Logger} log a message with * throwable * @return the builder */ public Builder throwableFormatter(ThrowableFormatter throwableFormatter) { this.throwableFormatter = throwableFormatter; return this; } /** * Set the thread formatter when {@link Logger} logging. * * @param threadFormatter the thread formatter when {@link Logger} logging * @return the builder */ public Builder threadFormatter(ThreadFormatter threadFormatter) { this.threadFormatter = threadFormatter; return this; } /** * Set the stack trace formatter when {@link Logger} logging. * * @param stackTraceFormatter the stace trace formatter when {@link Logger} logging * @return the builder */ public Builder stackTraceFormatter(StackTraceFormatter stackTraceFormatter) { this.stackTraceFormatter = stackTraceFormatter; return this; } /** * Set the border formatter when {@link Logger} logging. * * @param borderFormatter the border formatter when {@link Logger} logging * @return the builder */ public Builder borderFormatter(BorderFormatter borderFormatter) { this.borderFormatter = borderFormatter; return this; } /** * Add an object formatter for specific class of object when {@link Logger} log an object. * * @param objectClass the class of object * @param objectFormatter the object formatter to add * @param <T> the type of object * @return the builder * @since 1.1.0 */ public <T> Builder addObjectFormatter(Class<T> objectClass, ObjectFormatter<? super T> objectFormatter) { if (objectFormatters == null) { objectFormatters = new HashMap<>(DefaultsFactory.builtinObjectFormatters()); } objectFormatters.put(objectClass, objectFormatter); return this; } /** * Add an interceptor when {@link Logger} logging. * * @param interceptor the intercept to add * @return the builder * @since 1.3.0 */ public Builder addInterceptor(Interceptor interceptor) { if (interceptors == null) { interceptors = new ArrayList<>(); } interceptors.add(interceptor); return this; } /** * Set the printers used to print the log when {@link Logger} log. * * @param printers the printers used to print the log when {@link Logger} log * @return the builder */ public Builder printers(Printer... printers) { if (printers.length == 0) { // Is there anybody want to reuse the Builder? It's not a good idea, but // anyway, in case you want to reuse a builder and do not want the custom // printers anymore, just do it. this.printer = null; } else if (printers.length == 1) { this.printer = printers[0]; } else { this.printer = new PrinterSet(printers); } return this; } /** * Convenience of {@link #build()} and {@link Logger#v(Object)}. * * @since 1.1.0 */ public void v(Object object) { build().v(object); } /** * Convenience of {@link #build()} and {@link Logger#v(Object[])}. * * @since 1.4.0 */ public void v(Object[] array) { build().v(array); } /** * Convenience of {@link #build()} and {@link Logger#v(String, Object...)}. */ public void v(String format, Object... args) { build().v(format, args); } /** * Convenience of {@link #build()} and {@link Logger#v(String)}. */ public void v(String msg) { build().v(msg); } /** * Convenience of {@link #build()} and {@link Logger#v(String, Throwable)}. */ public void v(String msg, Throwable tr) { build().v(msg, tr); } /** * Convenience of {@link #build()} and {@link Logger#d(Object)}. * * @since 1.1.0 */ public void d(Object object) { build().d(object); } /** * Convenience of {@link #build()} and {@link Logger#d(Object[])}. * * @since 1.4.0 */ public void d(Object[] array) { build().d(array); } /** * Convenience of {@link #build()} and {@link Logger#d(String, Object...)}. */ public void d(String format, Object... args) { build().d(format, args); } /** * Convenience of {@link #build()} and {@link Logger#d(String)}. */ public void d(String msg) { build().d(msg); } /** * Convenience of {@link #build()} and {@link Logger#d(String, Throwable)}. */ public void d(String msg, Throwable tr) { build().d(msg, tr); } /** * Convenience of {@link #build()} and {@link Logger#i(Object)}. * * @since 1.1.0 */ public void i(Object object) { build().i(object); } /** * Convenience of {@link #build()} and {@link Logger#i(Object[])}. * * @since 1.4.0 */ public void i(Object[] array) { build().i(array); } /** * Convenience of {@link #build()} and {@link Logger#i(String, Object...)}. */ public void i(String format, Object... args) { build().i(format, args); } /** * Convenience of {@link #build()} and {@link Logger#i(String)}. */ public void i(String msg) { build().i(msg); } /** * Convenience of {@link #build()} and {@link Logger#i(String, Throwable)}. */ public void i(String msg, Throwable tr) { build().i(msg, tr); } /** * Convenience of {@link #build()} and {@link Logger#w(Object)}. * * @since 1.1.0 */ public void w(Object object) { build().w(object); } /** * Convenience of {@link #build()} and {@link Logger#w(Object[])}. * * @since 1.4.0 */ public void w(Object[] array) { build().w(array); } /** * Convenience of {@link #build()} and {@link Logger#w(String, Object...)}. */ public void w(String format, Object... args) { build().w(format, args); } /** * Convenience of {@link #build()} and {@link Logger#w(String)}. */ public void w(String msg) { build().w(msg); } /** * Convenience of {@link #build()} and {@link Logger#w(String, Throwable)}. */ public void w(String msg, Throwable tr) { build().w(msg, tr); } /** * Convenience of {@link #build()} and {@link Logger#e(Object)}. * * @since 1.1.0 */ public void e(Object object) { build().e(object); } /** * Convenience of {@link #build()} and {@link Logger#e(Object[])}. * * @since 1.4.0 */ public void e(Object[] array) { build().e(array); } /** * Convenience of {@link #build()} and {@link Logger#e(String, Object...)}. */ public void e(String format, Object... args) { build().e(format, args); } /** * Convenience of {@link #build()} and {@link Logger#e(String)}. */ public void e(String msg) { build().e(msg); } /** * Convenience of {@link #build()} and {@link Logger#e(String, Throwable)}. */ public void e(String msg, Throwable tr) { build().e(msg, tr); } /** * Convenience of {@link #build()} and {@link Logger#log(int, Object)}. * * @since 1.4.0 */ public void log(int logLevel, Object object) { build().log(logLevel, object); } /** * Convenience of {@link #build()} and {@link Logger#log(int, Object[])}. * * @since 1.4.0 */ public void log(int logLevel, Object[] array) { build().log(logLevel, array); } /** * Convenience of {@link #build()} and {@link Logger#log(int, String, Object...)}. * * @since 1.4.0 */ public void log(int logLevel, String format, Object... args) { build().log(logLevel, format, args); } /** * Convenience of {@link #build()} and {@link Logger#log(int, String)}. * * @since 1.4.0 */ public void log(int logLevel, String msg) { build().log(logLevel, msg); } /** * Convenience of {@link #build()} and {@link Logger#log(int, String, Throwable)}. * * @since 1.4.0 */ public void log(int logLevel, String msg, Throwable tr) { build().log(logLevel, msg, tr); } /** * Convenience of {@link #build()} and {@link Logger#json(String)}. */ public void json(String json) { build().json(json); } /** * Convenience of {@link #build()} and {@link Logger#xml(String)}. */ public void xml(String xml) { build().xml(xml); } /** * Builds configured {@link Logger} object. * * @return the built configured {@link Logger} object */ public Logger build() { return new Logger(this); } } }