XLog
Android logger, pretty, powerful and flexible, log to everywhere, save to file, all you want is here.
Install / Use
/learn @elvishew/XLogREADME
XLog
Lightweight and pretty, powerful and flexible logger for android and java, can print the log to Logcat, Console and Files, or anywhere if you like.
Logcat Output

Quick Start
Dependency
implementation 'com.elvishew:xlog:1.11.1'
Initialization
XLog.init(LogLevel.ALL);
Logging
XLog.d("hello xlog");
Logging
Log simple message.
XLog.d(message);
Log a message with throwable, usually use when exception is thrown.
XLog.e(message, throwable);
Format string is also supported, so you don't have to append so many strings and variables by +.
XLog.d("Hello %s, I am %d", "Elvis", 20);
Unformatted JSON and XML string will be formatted automatically.
XLog.json(JSON_CONTENT);
XLog.xml(XML_CONTENT);
All Collections and Maps data are supported.
XLog.d(array);
XLog.d(list);
XLog.d(map);
If needed, you can also dump Intent and Bundle object directly.
XLog.d(intent);
XLog.d(bundle);
In fact, you can dump any type of object if you want. You can specify an ObjectFormatter for specific type, otherwise toString() will be used when converting the object to a string.
XLog.d(object);
Note: v/d/i/w/e are optional, v for VERBOSE, d for DEBUG, i for INFO, w for WARNING and e for ERROR.
Config
xLog is very flexible, almost every component is configurable.
When initialization, there are a simple way
XLog.init(LogLevel.ALL);
and advance way.
LogConfiguration config = new LogConfiguration.Builder()
.logLevel(BuildConfig.DEBUG ? LogLevel.ALL // Specify log level, logs below this level won't be printed, default: LogLevel.ALL
: LogLevel.NONE)
.tag("MY_TAG") // Specify TAG, default: "X-LOG"
.enableThreadInfo() // Enable thread info, disabled by default
.enableStackTrace(2) // Enable stack trace info with depth 2, disabled by default
.enableBorder() // 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
.addInterceptor(new BlacklistTagsFilterInterceptor( // Add blacklist tags filter
"blacklist1", "blacklist2", "blacklist3"))
.addInterceptor(new MyInterceptor()) // Add other log interceptor
.build();
Printer androidPrinter = new AndroidPrinter(true); // Printer that print the log using android.util.Log
Printer consolePrinter = new ConsolePrinter(); // Printer that print the log to console using System.out
Printer filePrinter = new FilePrinter // Printer that print(save) the log to file
.Builder("<path-to-logs-dir>") // Specify the directory path of log file(s)
.fileNameGenerator(new DateFileNameGenerator()) // Default: ChangelessFileNameGenerator("log")
.backupStrategy(new NeverBackupStrategy()) // Default: FileSizeBackupStrategy(1024 * 1024)
.cleanStrategy(new FileLastModifiedCleanStrategy(MAX_TIME)) // Default: NeverCleanStrategy()
.flattener(new MyFlattener()) // Default: DefaultFlattener
.writer(new MyWriter()) // Default: SimpleWriter
.build();
XLog.init( // Initialize XLog
config, // Specify the log configuration, if not specified, will use new LogConfiguration.Builder().build()
androidPrinter, // Specify printers, if no printer is specified, AndroidPrinter(for Android)/ConsolePrinter(for java) will be used.
consolePrinter,
filePrinter);
After initialization, a global Logger with the global config is created, all logging via XLog will pass to this global Logger.
Besides, you can create unlimmited number of Logger with different configs:
- Base on global
Logger, change tag to"TAG-A".
Logger logger = XLog.tag("TAG-A")
... // other overrides
.build();
logger.d("Message with custom tag");
- Base on global
Logger, enable border and thread info.
Logger logger = XLog.enableBorder()
.enableThread()
... // other overrides
.build();
logger.d("Message with thread info and border");
you can also log with one-time-use config:
XLog.tag("TAG-A").d("Message with custom tag");
XLog.enableBorder().enableThread().d("Message with thread info and border");
Print to anywhere
With one logging statement
XLog.d("hello xlog");
you can print the "hello xlog" to
-
Logcat (with
AndroidPrinter) -
File (with
FilePrinter)
and anywhere you like.
Just implement the Printer interface, and specify it when initializing
XLog.init(config, printer1, printer2...printerN);
or when creating a non-global Logger
Logger logger = XLog.printer(printer1, printer2...printerN)
.build();
or when one-time-use logging
XLog.printer(printer1, printer2...printerN).d("Message with one-time-use printers");
Save logs to file
To save logs to file, you need to create a FilePrinter
Printer filePrinter = new FilePrinter // Printer that print(save) the log to file
.Builder("<path-to-logs-dir>") // Specify the directory path of log file(s)
.fileNameGenerator(new DateFileNameGenerator()) // Default: ChangelessFileNameGenerator("log")
.backupStrategy(new NeverBackupStrategy()) // Default: FileSizeBackupStrategy(1024 * 1024)
.cleanStrategy(new FileLastModifiedCleanStrategy(MAX_TIME)) // Default: NeverCleanStrategy()
.flattener(new MyFlattener()) // Default: DefaultFlattener
.build();
and add the FilePrinter to XLog when initializing
XLog.init(config, filePrinter);
or when creating an non-global Logger
Logger logger = XLog.printer(filePrinter)
... // other overrides
.build();
or when one-time-use logging
XLog.printer(filePrinter).d("Message with one-time-use printers");
Save third party logs
You can config LibCat after initializing XLog.
LibCat.config(true, filePrinter);
Then, the logs logged by third party modules/libraries(within same app) will be saved to file too.
Go to [LibCat] for more details.
Custom file name
You can specify the file name directly, or categorize the logs to different files by some rules.
- Use
ChangelessFileNameGenerator, you can specify a changeless file name.
logs-dir
└──log
- Use
LevelFileNameGenerator, it will categorize logs by levels automatically.
logs-dir
├──VERBOSE
├──DEBUG
├──INFO
├──WARN
└──ERROR
- Use
DateFileNameGenerator, it will categorize logs by date automatically.
logs-dir
├──2020-01-01
├──2020-01-02
├──2020-01-03
└──2020-01-04
- Implement
FileNameGeneratordirectly, make the file name generating rules by yourself.
logs-dir
├──2020-01-01-<hash1>.log
├──2020-01-01-<hash2>.log
├──2020-01-03-<hash>.log
└──2020-01-05-<hash>.log
By default, a ChangelessFileNameGenerator with log file name log is used.
Custom log format
Log elements(date, time, level and message) should be flattened to a single string before being printed to the file, you need a Flattener to do that.
We have defined a PatternFlattener, which may satisfy most of you. All you need to do is just passing a pattern with parameters to the flattener.
Supported parameters:
|Parameter|Represents| |:---:|---| |{d}|Date in default date format "yyyy-MM-dd HH:mm:ss.SSS"| |{d format}|Date in specific date format| |{l}|Short name of log level. e.g: V/D/I| |{L}|Long name of log level. e.g: VERBOSE/DEBUG/INFO| |{t}|Tag of log| |{m}|Message of log|
Imagine there is a log, with DEBUG level, "my_tag" tag and "Simple message" message, the flattened log would be as below.
|Pattern|Flattened log| |:---:|---| |{d} {l}/{t}: {m}|2016-11-30 13:00:00.000 D/my_tag: Simple message| |{d yyyy-MM-dd HH:mm:ss.SSS} {l}/{t}: {m}|2016-11-30 13:00:00.000 D/my_tag: Simple message| |{d yyyy/MM/dd HH:mm:ss} {l}|{t}: {m}|2016/11/30 13:00:00 D|my_tag: Simple message| |{d yy/MM/dd HH:mm:ss} {l}|{t}: {m}|16/11/30 13:00:00 D|my_tag: Simple message| |{d MM/dd HH:mm} {l}-{t}-{m}|11/30 13:00 D-my_tag-Simple message|
If you don't even want to construct a pattern, ClassicFlattener is for you. It is a PatternFlattener with a default pattern {d} {l}/{t}: {m}.
By default, FilePrinter use a DefaultFlattener, which just simply concat the timestamp and message together. You may don't like it, so please remember to specify your own Flattener, maybe a ClassicFlattener.
