Tencent's XLog Remains the Only Self-Contained Android Logging Library That Doesn't Lock You Out of Your Own Data
Why You Need Online Log Printing
For most applications, online logging is not really necessary. As long as you integrate Umeng or Bugly, the information they provide is sufficient to resolve exceptions that occur. However, the problem is that not all issues cause crashes. Especially for business-heavy applications, an incorrect amount displayed won't crash the app, but it will definitely crash the user. You cannot solve this kind of problem by looking up information on an app statistics platform. You can only use an online logging framework to print relevant business processes to find out where the problem lies.
Therefore, when you realize that the Android system's android.util.Log can no longer meet your needs, congratulations — your application has gained enough users or business. These users and businesses can bring you significant profits, but they also bring technical challenges, driving you to build the infrastructure for online environment log printing.
Currently Available Online Log Printing Solutions
There aren't many good choices for online environment logging solutions on Android, mainly due to one factor: performance.
If performance were not a concern, we could write logs to disk using any method, standard file I/O or direct I/O. But in an online environment, this is not feasible. Massive I/O inevitably causes performance overhead, ranging from lag to ANR. Therefore, we need to choose a solution that is acceptable in terms of performance.
If you search, you can see several available solutions: Timber, Logger, Logan, XLog. Among them, Timber and Logger are just wrappers around android.util.Log and do not consider persistence. The real choice is between XLog and Logan.
XLog vs Logan
Both of these logging solutions use mmap storage + AES encryption, and neither has performance issues.
XLog is a logging solution released by Tencent: Tencent Mars-XLog Github. However, since its public release, Tencent has not maintained this library. Of course, only the externally provided version has not been updated or supported; the version used internally must have remained active. You can observe that the latest date on Github is from 9 years ago, which is characteristic of large companies: to meet KPIs or gain influence, they publish some technical solutions to attract a wave of attention. When the hype fades, these codes that were once in the spotlight are all thrown into the trash.
In contrast, Logan: Meituan-Dianping Log System-Github, this online logging solution provided by Meituan, has better SDK quality and more active maintenance. However, it is not just an online logging framework but a complete logging system including client-side printing, log retrieval, front-end services, etc. When you use this log system, you will find that you need to set up and use its entire system, and your workflow must be tightly bound to Meituan's logging system. Otherwise, you cannot even decrypt the logs.
Here's a detail: online logs based on mmap like XLog and Logan are almost impossible to output directly in plain text. They must be compressed and encrypted, and the generated log files are in binary format. XLog provides a decoding script, while Logan requires setting up its provided log service to decrypt. The differences between the two are as follows:
| Comparison Dimension | XLog | Logan |
|---|---|---|
| Official Decryption Tool | ✅ Provides Python decryption script | ❌ Only by setting up Logan Server can decrypt |
| Encryption Can Be Disabled | ✅ Optional plaintext mode, easy debugging | ❌ Mandatory encryption, initialization fails without Key/IV |
| Multi-platform Support | iOS/Android/Mac | iOS/Android/Web/Flutter/Mini Programs |
| Log Retrieval | ❌ Requires self-built | ✅ Built-in |
| Maven Central | ❌ Not published | ✅ Published |
| Maintenance Status | Effectively abandoned (Last Release 2018) | Active |
Why Choose XLog
From the above, it's clear that the current choices for online log printing are basically XLog and Logan. So why choose XLog instead of Logan here? Actually, there is only one reason: Meituan does not provide an official decryption tool.
Compared to Logan, XLog's problems are not really problems: although it's not updated, it works; although the .so is not 16K aligned, it works; although it's not published to mavenCentral, the aar works. In short, it's not unusable. No matter how many problems there are, it's better than having no official decryption tool.
XLog Integration and Usage
XLog's integration documentation is also explained in its Github, but it's outdated, and many APIs have changed. The content described there is basically useless for reference. Reading it not only wastes time but also causes delays.
Integration
Originally, XLog was uploaded by Tencent to jcenter, but after jcenter shut down, Tencent did not maintain it. Currently, XLog is in a verve repository:
//settings.gradle.kts
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
// ......
// mars-xlog is currently only available in this repository, but this repository is a public repository of a company, and its stability is uncertain:
// https://verve.jfrog.io/ui/repos/tree/General/verve-gradle-jcenter-cache/com/tencent/mars/mars-xlog/1.2.6
maven {
url = uri("https://verve.jfrog.io/artifactory/verve-gradle-release")
}
}
}
Then introduce xlog in the module:
dependencies {
// Download from verve's public repository
implementation("com.tencent.mars:mars-xlog:1.2.6")
// implementation(files("libs/mars-xlog-1.2.6.aar")) Suggest downloading aar locally
}
However, it is still recommended to directly download the aar file for dependency. After all, everyone knows what the internet in China is like. If it can be placed locally, place it locally. No one likes Gradle spinning there for hours. Therefore, I chose the local aar file.
ProGuard
This was actually not mentioned in the official documentation, but if not set, initialization will fail when building the RELEASE package.
ProGuard file consumer-rules.keep:
# Keep XLog's JNI classes, cannot be obfuscated
-keep class com.tencent.mars.** { *; }
-keep class com.tencent.mars.xlog.** { *; }
# Keep native methods (JNI entry points)
-keepclasseswithmembernames class * {
native <methods>;
}
# XLog's Log entity classes (if used)
-keep class com.tencent.mars.utils.** { *; }
Then configure in the module:
android {
// ......
defaultConfig {
// mars-xlog's AAR only contains .so for armeabi-v7a and arm64-v8a architectures
ndk {
abiFilters += listOf("armeabi-v7a", "arm64-v8a")
}
consumerProguardFiles("consumer-rules.keep")
}
}
Also, pay attention to the ndk configuration here. XLog only provides .so for two ABIs, so you need to limit the target device architecture.
Initialization
Below is the initialization code for XLog:
System.loadLibrary("c++_shared");
System.loadLibrary("marsxlog");
Log.setLogImp(new Xlog());
Log.appenderOpen(isDebug ? Xlog.LEVEL_VERBOSE : Xlog.LEVEL_INFO,
Xlog.AppednerModeAsync,
context.getFilesDir().getAbsolutePath() + File.separator + "xlogmmap",
context.getFilesDir().getAbsolutePath() + File.separator + "xlog",
Application.getProcessName(),
0);
Log.setConsoleLogOpen(isDebug);
After the above setup, you can use the following code for log printing:
package com.tencent.mars.xlog;
public class Log {
public static void f(String tag, String msg)
public static void e(String tag, String msg)
public static void w(String tag, String msg)
public static void i(String tag, String msg)
public static void d(String tag, String msg)
public static void v(String tag, String msg)
}
Of course, XLog provides more than just these methods. Below, we will explain the purpose of these methods one by one.
Related APIs
Log.appenderOpen
public static void appenderOpen(int level, int mode, String cacheDir, String logDir, String nameprefix, int cacheDays)
- level: Log level, same as the system Log, from LEVEL_VERBOSE to LEVEL_FATAL. Can also be set via the
setLogLevelmethod. - mode: Write mode,
AppednerModeAsyncfor asynchronous writing;AppednerModeSyncfor synchronous writing. Can also be set via thesetAppenderModemethod. - cacheDir: Set the cache directory. It is recommended to use the app's
/data/data/packname/files/logdirectory. Cache files with the suffix.mmap3will be generated in this directory. - logDir: Set the directory for written files. The directory where the generated
.xloglogs are written. A separate path needs to be set. - nameprefix: Set the prefix for log file names. For example, if this value is TEST, the generated file name will be:
TEST_20170102.xlog. - cacheDays: Indicates after how many days the log files will be moved from cacheDir to logDir. Generally, fill in 0.
Log.setConsoleLogOpen
public static void setConsoleLogOpen(boolean isOpen)
Set whether to print logs in the console. It is recommended to turn it on in DEBUG and off in RELEASE.
Log.appenderClose
public static void appenderClose()
The official documentation says to close the log when the program exits, but in practice, there is basically no opportunity to call this method. The onTerminate() method of the Application class only takes effect in the emulator. Therefore, it can be ignored.
Log.appenderFlush()
public static void appenderFlush()
public static void appenderFlushSync(boolean isSync)
Flush the log content in memory to the file.
Precautions for Using XLog
XLog Decompression
Logs generated using XLog have the suffix .xlog, and their content is in binary format. They need to be decoded before viewing. The currently official decoding script is: mars/mars/xlog/crypt/decode_mars_nocrypt_log_file.py at master · Tencent/mars
Use the following command to decode:
python decode_mars_nocrypt_log_file_py3.py <xlog file or directory>
At this point, a decoded log file will be generated in the same folder as the xlog file. However, note that the Python version required by the officially provided Python file might be very old.
Multiple Dependent Libraries
If your application depends on many libraries, and if these libraries all use XLog, then when you use it, due to XLog's global singleton design pattern, which is basically all static methods, configuration conflicts may occur. In this case, you can consider XLog's multi-instance methods or unify the configuration parameters.
Top 2 of 4 from juejin.cn, machine-translated. The original thread is authoritative.
Logan's decryption logic can just be copied out from the server side. On the contrary, the real headache with XLog is that it doesn't maintain 16KB alignment and other such issues [sweat]
16KB compilation — just add an option in CMake.
This can be solved with zipalign or by recompiling.
Fork a copy and package it yourself for 16KB is very simple, AI can do it in one shot.