Simple and pretty, powerful and flexible logger for android and java, can concurrently print the log to multiple target like Logcat, System.out and File, or even Server(or anywhere) if you like.
What XLog can do:
- Global config(tag, formatters...) or log-based config
- Support printing any object and customizable object formatter
- Support printing array
- Support printing long log (No 4K limitation)
- XML and JSON formatted
- Thread information (Thread name etc. Can be customized)
- Stack trace information (Configurable call stack depth, with file name, method name, line number)
- Save logs in file (Configurable file naming and backup strategy)
- Good looking in Android Studio
- Easy to use, powerful in customization
The differences to other logger libraries:
- Pretty source code and document
- So flexible that you can easily customize or enhance it
- Lightweight, no other dependencies
compile 'com.elvishew:xlog:1.2.1'
- Log with thread information, stack trace information and border
XLog.init(LogLevel.ALL);
Or if you want to disable the log in release version
XLog.init(BuildConfig.DEBUG ? LogLevel.ALL : LogLevel.NONE);
LogConfiguration config = new LogConfiguration.Builder()
.tag("MY_TAG") // Specify TAG, default: "X-LOG"
.t() // Enable thread info, disabled by default
.st(2) // Enable stack trace info with depth 2, disabled by default
.b() // Enable border, disabled by default
.jsonFormatter(new MyJsonFormatter()) // Default: DefaultJsonFormatter
.xmlFormatter(new MyXmlFormatter()) // Default: DefaultXmlFormatter
.throwableFormatter(new MyThrowableFormatter()) // Default: DefaultThrowableFormatter
.threadFormatter(new MyThreadFormatter()) // Default: DefaultThreadFormatter
.stackTraceFormatter(new MyStackTraceFormatter()) // Default: DefaultStackTraceFormatter
.borderFormatter(new MyBoardFormatter()) // Default: DefaultBorderFormatter
.addObjectFormatter(AnyClass.class, // Add formatter for specific class of object
new AnyClassObjectFormatter()) // Use Object.toString() by default
.build();
Printer androidPrinter = new AndroidPrinter(); // Printer that print the log using android.util.Log
Printer SystemPrinter = new SystemPrinter(); // Printer that print the log using System.out.println
Printer filePrinter = new FilePrinter // Printer that print the log to the file system
.Builder("/sdcard/xlog/") // Specify the path to save log file
.fileNameGenerator(new DateFileNameGenerator()) // Default: ChangelessFileNameGenerator("log")
.backupStrategy(new MyBackupStrategy()) // Default: FileSizeBackupStrategy(1024 * 1024)
.logFlattener(new MyLogFlattener()) // Default: DefaultLogFlattener
.build();
XLog.init(LogLevel.ALL, // Specify the log level, logs below this level won't be printed
config, // Specify the log configuration, if not specified, will use new LogConfiguration.Builder().build()
androidPrinter, // Specify printers, if no printer is specified, AndroidPrinter will be used by default
systemPrinter,
filePrinter);
For android, a best place to do the initialization is Application.onCreate().
XLog.d("Simple message")
XLog.d("My name is %s", "Elvis");
XLog.d("An exception caught", exception);
XLog.d(object);
XLog.d(array);
XLog.json(unformattedJsonString);
XLog.xml(unformattedXmlString);
... // Other global usage
Build a logger.
Logger partial = XLog.tag("PARTIAL-LOG")
... // Other configs
.build();
And use it partially, the logging methods is completely the same as that ones in XLog.
partial.d("Simple message 1");
partial.d("Simple message 2");
... // Other partial usage
Setup log-based configs and log immediately, the logging methods is completely the same as that ones in XLog.
XLog.t() // Enable thread into
.st(3) // Enable stack trace info with depth 3
.b() // Enable border
... // Other configs
.d("Simple message 1");
XLog.tag("TEMP-TAG")
.st(0) // Enable stack trace info without limitation
... // Other configs
.d("Simple message 2");
XLog.nt() // Disable thread info
.nst() // Disable stack trace info
.d("Simple message 3");
XLog.b().d("Simple message 4");
Let's imagine there are a JSON string and a XML string
String jsonString = "{\"name\": \"Elvis\", \"age\": 18}";
String xmlString = "<team><member name="Elvis"/><member name="Leon"/></team>";
Log.d(TAG, "Message");
Log.d(TAG, String.format("Message with argument: age=%s", 18));
Log.d(TAG, jsonString);
Log.d(TAG, xmlString);
Log.d(TAG, "Message with stack trace info", new Throwable());
XLog.init(LogLevel.ALL);
XLog.d("Message");
XLog.d("Message with argument: age=%s", 18);
XLog.json(jsonString);
XLog.xml(xmlString);
XLog.st(5).d("Message with stack trace info");
XLog.init(LogLevel.ALL, new LogConfiguration.Builder().b().build());
XLog.d("Message");
XLog.d("Message with argument: age=%s", 18);
XLog.json(jsonString);
XLog.xml(xmlString);
XLog.st(5).d("Message with stack trace info");
In order to be compatible with Android Log, all the methods of Android Log are supported here.
See the Log class defined in XLog.
Log.v(String, String);
Log.v(String, String, Throwable);
Log.d(String, String);
Log.d(String, String, Throwable);
Log.i(String, String);
Log.i(String, String, Throwable);
Log.w(String, String);
Log.w(String, String, Throwable);
Log.wtf(String, String);
Log.wtf(String, String, Throwable);
Log.e(String, String);
Log.e(String, String, Throwable);
Log.println(int, String, String);
Log.isLoggable(String, int);
Log.getStackTraceString(Throwable);
If you have a big project using the Android Log, and it is a hard work to change all usage of Android Log to XLog, then you can use the compatible API, simply replace all 'android.util.Log' to 'com.elvishew.xlog.XLog.Log'.
(For a better performance, you should think about not using the compatible API.)
grep -rl "android.util.Log" <your-source-directory> | xargs sed -i "s/android.util.Log/com.elvishew.xlog.XLog.Log/g"
grep -rl "android.util.Log" <your-source-directory> | xargs sed -i "" "s/android.util.Log/com.elvishew.xlog.XLog.Log/g"
In 'Project' pane, switch to the 'Project Files' tab, then right-click on the your source directory.
In the menu, click the 'Replace in Path...' option.
In the dialog, fill the 'Text to find' with 'android.util.Log', and 'Replace with' with 'com.elvishew.xlog.XLog.Log', and click 'Find'.
- Print any object: XLog.d(Object) (since 1.1.0)
- Support log interceptors(similar to okhttp's Interceptor, here we use it for intercepting log) (since 1.3.0)
- Add tags filter (blacklist filter and whitelist filter) (since 1.3.0)
- Add PatternLogFlattener(mostly used when logging to file), e.g: "{time} {level}/{tag}: {msg}" means "2016-10-30 13:00:00,000 W/my_tag: Simple message"
If you meet any problem when using XLog, or have any suggestion, please feel free to create an issue.
Thanks to Orhan Obut's logger, it give me many ideas of what a logger can do.
Thanks to Serge Zaitsev's log, it give me the thought of making XLog compatible with Android Log.
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.