{"id":35891246,"url":"https://github.com/jenly1314/LogX","last_synced_at":"2026-01-15T16:00:42.251Z","repository":{"id":236795897,"uuid":"793164368","full_name":"jenly1314/LogX","owner":"jenly1314","description":":triangular_flag_on_post: LogX 一个轻量而强大的日志框架；好用不解释。","archived":false,"fork":false,"pushed_at":"2025-05-11T10:17:09.000Z","size":6211,"stargazers_count":20,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-11T10:25:17.449Z","etag":null,"topics":["android","kotlin","log","log-printer","logcat","logger","timber"],"latest_commit_sha":null,"homepage":"https://jenly1314.github.io/LogX/","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jenly1314.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-04-28T15:58:28.000Z","updated_at":"2025-05-11T10:17:12.000Z","dependencies_parsed_at":"2024-04-28T17:24:56.938Z","dependency_job_id":"224b3e4c-e8ca-494a-9d42-00b8f8f79c33","html_url":"https://github.com/jenly1314/LogX","commit_stats":null,"previous_names":["jenly1314/logx"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/jenly1314/LogX","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenly1314%2FLogX","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenly1314%2FLogX/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenly1314%2FLogX/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenly1314%2FLogX/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jenly1314","download_url":"https://codeload.github.com/jenly1314/LogX/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenly1314%2FLogX/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28458636,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-15T15:17:48.816Z","status":"ssl_error","status_checked_at":"2026-01-15T15:16:50.052Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","kotlin","log","log-printer","logcat","logger","timber"],"created_at":"2026-01-09T08:00:27.098Z","updated_at":"2026-01-15T16:00:42.234Z","avatar_url":"https://github.com/jenly1314.png","language":"Kotlin","funding_links":[],"categories":["Kotlin"],"sub_categories":[],"readme":"# LogX\n\n[![MavenCentral](https://img.shields.io/maven-central/v/com.github.jenly1314/logx?logo=sonatype)](https://repo1.maven.org/maven2/com/github/jenly1314/logx)\n[![JitPack](https://img.shields.io/jitpack/v/github/jenly1314/LogX?logo=jitpack)](https://jitpack.io/#jenly1314/LogX)\n[![CI](https://img.shields.io/github/actions/workflow/status/jenly1314/LogX/build.yml?logo=github)](https://github.com/jenly1314/LogX/actions/workflows/build.yml)\n[![Download](https://img.shields.io/badge/download-APK-brightgreen?logo=github)](https://raw.githubusercontent.com/jenly1314/LogX/master/app/release/app-release.apk)\n[![API](https://img.shields.io/badge/API-21%2B-brightgreen?logo=android)](https://developer.android.com/guide/topics/manifest/uses-sdk-element#ApiLevels)\n[![License](https://img.shields.io/github/license/jenly1314/LogX?logo=open-source-initiative)](https://opensource.org/licenses/apache-2-0)\n\n**LogX** —— 轻量而强大的日志框架，兼具 **Timber** 的优雅易用与高度扩展性，同时拥有 **Logger** 般精美的日志格式化输出。\n\n\u003e写这个日志框架的主要原因是为了简化维护流程。在我个人的GitHub开源项目中，有一些需要使用日志功能的库。\n\u003e最初，我使用的是一个自维护日志工具类：LogUtils，当开源项目数量较少时，这种方法还比较有效。\n\u003e然而，随着开源项目数量的增加，我不得不频繁地复制和维护LogUtils，随着时间的推移，不同开源项目中的LogUtils可能会\n\u003e出现一些差异，这大大增加了维护的难度。因此，我开始考虑更加优雅的解决方案。在经过一段时间的思考和研究后，我决定\n\u003e结合平时使用的 [Timber](https://github.com/JakeWharton/timber) 和 [Logger](https://github.com/orhanobut/logger) 这\n\u003e两个成熟的开源库，取其精华，编写一个新的日志框架，即：**LogX** 。\n\n## 类图\n\n![Image](art/logx_uml.png)\n\n\u003e 从上面的类图可以明确的看出 **LogX** 内部之间的关系与结构。\n\n## 引入\n\n### Gradle:\n\n1. 在Project的 **build.gradle** 或 **setting.gradle** 中添加远程仓库\n\n    ```gradle\n    repositories {\n        //...\n        mavenCentral()\n    }\n    ```\n\n2. 在Module的 **build.gradle** 中添加依赖项\n\n    ```gradle\n    implementation 'com.github.jenly1314:logx:1.2.0'\n    ```\n\n## 使用\n\n### 快速使用\n\n如果没有特殊的要求，直接使用即可。\n\n\u003e **LogX** 无需初始化，因为 **LogX** 的默认配置就是个人最推荐的配置。（这也是我写 **LogX** 的原因之一）\n\n主要的一些方法调用示例如下：\n\n```java\nLogX.v(\"verbose\");\nLogX.d(\"debug\");\nLogX.i(\"info\");\nLogX.w(\"warn\");\nLogX.e(\"error\");\nLogX.wtf(\"assert\");\n\n```\n\n占位符格式化示例如下:\n\n```java\nLogX.d(\"hello %s\", \"world\");\n```\n\n\u003e 看了上面的基础说明，相信你已经会使用 **LogX** 了；如果还想了解更多，你可以继续往下看更多详细说明。\n\n### 详细说明\n\n#### Logger实现类说明\n\n**LogX** 中内置实现了一些常用的`Logger`，用于满足基本的开发需求；下面简单概括下各`Logger`实现类的特点与适用场景。\n\n**DefaultLogger**\n\n* **特点：** 输出日志到`Logcat`，轻量高效，支持日志分级及超长日志自动拆分。\n* **适用场景：** 开发调试、高频日志打印，适合快速排查问题。\n\n**FileLogger**\n\n* **特点：** 持久化日志到文件，支持滚动存储与自动清理旧日志，确保存储空间高效利用。\n* **适用场景：** 生产环境问题追踪、离线日志分析。\n\n\u003e `FileLogger` 在持久化日志到文件的同时，也支持同时将日志输出到`Logcat`（需根据配置决定）。\n\n**CompositeLogger**\n\n* **特点：** 组合多个`Logger`，统一分发日志，灵活管理多路输出。\n* **适用场景：** 开发与生产环境并行，多维度日志收集，动态调整日志策略。\n\n#### 使用指南\n\n**DefaultLogger \u0026 FileLogger**\n\n- 使用方法基本一致\n- 区别仅在于配置参数的复杂度（`FileLogger`可配置项更多）\n- 具体用法可参考`DefaultLogger`的配置示例\n\n下面就以`DefaultLogger`为例，介绍下配置步骤；\n\n一句话概括：通过构建`DefaultLoggerConfig`完成参数配置，实例化`DefaultLogger`后，设置给`LogX`即可生效。\n\nJava配置示例：\n\n```java\n\nDefaultLoggerConfig config = new DefaultLoggerConfig.Builder()\n    .setLogFormat(LogFormat.PRETTY) // 设置日志显示格式（默认：LogFormat.PRETTY）\n    .setShowThreadInfo(true) // 设置是否显示线程信息（默认：true）\n    .setMethodCount(2) // 设置要显示的调用栈方法行数（默认：2）\n    .build();\nLogger logger = new DefaultLogger(config);\n\nLogX.setLogger(logger);\n\n```\n\nKotlin配置示例：\n\n\u003e 虽然`Kotlin`也能用`Builder`来创建实例，但使用`Kotlin DSL`更简洁。\n\n```kotlin\n// DSL\nval config = DefaultLoggerConfig.build {\n    logFormat = LogFormat.PRETTY // 设置日志显示格式（默认：LogFormat.PRETTY）\n    showThreadInfo = true // 设置是否显示线程信息（默认：true）\n    methodCount = 2 // 设置要显示的调用栈方法行数（默认：2）\n}\nval logger = DefaultLogger(config)\n\nLogX.setLogger(logger)\n\n```\n\n\u003e `LogFormat`为v1.2.0新增，这里不过多介绍，下面会有`LogFormat`相关说明。\n\n全局配置是否记录日志示例如下：\n\n```java\nLogX.setLogger(new DefaultLogger() {\n   @Override\n   protected boolean isLoggable(int priority, @Nullable String tag) {\n//       return super.isLoggable(priority, tag);\n        // 例如：只在开发模式才记录日志\n       return BuildConfig.DEBUG;\n       // 例如：根据priority控制\n//       return priority \u003e= LogX.DEBUG;\n   }\n});\n```\n\u003e **LogX** 默认配置就是在debug包下才开启日志记录的，release包默认是关闭日志记录的。\n\n**CompositeLogger**\n\n- 采用组合模式统一管理多个`Logger`\n- 支持多路日志并行输出\n\n使用`CompositeLogger`管理`Logger`的示例如下：\n\n```java\n// CompositeLogger可添加任意的Logger实现\nCompositeLogger compositeLogger = new CompositeLogger();\n// 例如：添加 DefaultLogger\ncompositeLogger.addLogger(new DefaultLogger());\n// 例如：添加 FileLogger\ncompositeLogger.addLogger(new FileLogger(context) {\n    @Override\n    protected boolean isLoggable(int priority, @Nullable String tag) {\n        // 例如：警告或警告以上级别日志持久化到日志文件\n        return priority \u003e= LogX.WARN;\n    }\n});\n\nLogX.setLogger(compositeLogger);\n```\n\n\u003e 如以上内置的功能都不满足你的需求，你还可以自定义实现一个`Logger`。\n\n### 日志效果\n\n日志的默认输出格式如下：\n\n```\n ┌──────────────────────────────\n │ Thread information\n ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄\n │ Method stack history\n ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄\n │ Log message\n └──────────────────────────────\n```\n在Logcat中的实际效果如下：\n\n![Image](art/logx_output.png)\n\n\u003e 这里的日志效果，对应的日志格式是：`LogFormat.PRETTY`，下面会有`LogFormat`相关说明。\n\n### 特别说明\n\n`LogX`中提供了一些可链式调用的一些小功能，用于满足一些特定需求场景。\n\n#### 关于 **LogX.tag(tag)**\n\n`LogX.tag(tag)`的主要作用：为下次日志调用设置一次性tag。\n\n未指定tag时，默认自动通过调用栈获取简单类名作为tag。如需自定义tag，可使用`LogX.tag(tag)`进行指定。\n\n`LogX.tag(tag)` 使用示例：\n```java\n// 指定tag\nLogX.tag(\"MyTag\").d(\"debug\");\n```\n\n#### 关于`LogX.offset(methodOffset)`\n\n`LogX.offset(methodOffset)`的主要作用：为下次日志调用设置一次性方法跟踪偏移量。\n\n**LogX** 支持类似的堆栈偏移调整功能。当迁移现有实现时，使用`LogX.offset(methodOffset)`可保持原有的日志定位准确性，同时获得 **LogX** 增强的格式化输出效果。\n\n示例1：如果之前用的[Timber](https://github.com/JakeWharton/timber)，现通过使用`LogX.offset(methodOffset)` 转到 `LogX`\n\n```java\n    Timber.plant(new Timber.Tree() {\n        @Override\n        protected boolean isLoggable(@Nullable String tag, int priority) {\n            return BuildConfig.DEBUG;\n        }\n\n        @Override\n        protected void log(int priority, @Nullable String tag, @NonNull String message, @Nullable Throwable throwable) {\n//            if (tag != null) { // 这里的tag可要可不要\n//                LogX.tag(tag);\n//            }\n            // 在Timber目前层级没发生变化的情况下，方法栈偏移4 即可准确定位到原始Timber调用的代码所在行。（这里不需要throwable，因为message里面已经包含了）\n            LogX.offset(4).log(priority, message);\n        }\n    });\n\n```\n\n示例2：如果之前用的[Logger](https://github.com/orhanobut/logger)，现通过使用`LogX.offset(methodOffset)` 转到 `LogX`\n\n```java\n    Logger.addLogAdapter(new LogAdapter() {\n        @Override\n        public boolean isLoggable(int priority, @Nullable String tag) {\n            return BuildConfig.DEBUG;\n        }\n\n        @Override\n        public void log(int priority, @Nullable String tag, @NonNull String message) {\n//            if(tag != null) { // 这里的tag可要可不要\n//                LogX.tag(tag);\n//            }\n            // 在Logger目前层级没发生变化的情况下，方法栈偏移5 即可准确定位到原始Logger调用的代码所在行。\n            LogX.offset(5).log(priority, message);\n        }\n    });\n\n```\n\n\u003e 通过使用`LogX.offset(methodOffset)`进行方法栈的偏移，就算多库混用也互不影响，都能够精确定位到日志对应的代码行。\n\n#### 关于`LogX.format(logFormat)`（v1.2.0新增）\n\n未指定logFormat时，默认使用通过`Logger`构造参数配置项的`logFormat`，如需指定logFormat，可使用`LogX.format(logFormat)`进行指定。\n\n`LogX.format(logFormat)`的主要作用：为下次日志调用设置一次性日志显示格式。\n\n**`LogX.format(logFormat)`的日志格式（即：`LogFormat`）选择：**\n\n##### LogFormat格式说明\n\n- `LogFormat.PRETTY` - 美化格式（默认），带结构化分隔线的日志排版，提升可读性，便于开发调试时快速定位问题；\n- `LogFormat.PLAIN` - 普通格式，与Android原生日志格式一致，适用于：高频日志输出，调用栈不重要的场景。\n\n使用`LogX.format(logFormat)`实时切换，平衡可读性与性能。\n\n`LogX.format(logFormat)` 使用示例：\n\n```java\n// 指定logFormat\nLogX.format(LogFormat.PLAIN).d(\"original log message\");\n```\n\n### 关于`FormatUtils`（v1.1.0新增）\n\n格式化`json`和`xml`本不属于日志打印的范畴，但为了提升可读性和美观性，决定提供一个工具类`FormatUtils`来支持此功能。至于是否需要格式化，由开发者根据实际需求自行决定。\n\n#### 格式化json示例：\n```java\nString json = \"{\\\"key\\\": \\\"value\\\", \\\"array\\\":[\\\"item1\\\",\\\"item2\\\"]}\";\n// 打印格式化后的json\nLogX.d(FormatUtils.formatJson(json));\n\n```\n\n#### 格式化xml示例：\n```java\nString xml = \"\u003croot\u003e\u003ckey\u003evalue\u003c/key\u003e\u003carray\u003e\u003citem\u003eitem1\u003c/item\u003e\u003citem\u003eitem2\u003c/item\u003e\u003c/array\u003e\u003c/root\u003e\";\n// 打印格式化后的xml\nLogX.d(FormatUtils.formatXml(xml));\n```\n\n更多使用详情，请查看[app](app)中的源码使用示例或直接查看[API帮助文档](https://jenly1314.github.io/LogX/api/)\n\n## 相关推荐\n\n- [MVVMFrame](https://github.com/jenly1314/MVVMFrame) 一个基于Google官方推出的JetPack构建的MVVM快速开发框架。\n- [ZXingLite](https://github.com/jenly1314/ZXingLite) 基于zxing实现的扫码库，优化扫码和生成二维码/条形码功能。\n- [MLKit](https://github.com/jenly1314/MLKit) 一个强大易用的工具包。通过ML Kit您可以很轻松的实现文字识别、条码识别、图像标记、人脸检测、对象检测等功能。\n- [WeChatQRCode](https://github.com/jenly1314/WeChatQRCode) 基于OpenCV开源的微信二维码引擎移植的扫码识别库。\n- [CameraScan](https://github.com/jenly1314/CameraScan) 一个简化扫描识别流程的通用基础库。\n\n\u003c!-- end --\u003e\n\n## 版本日志\n\n#### v1.2.0：2025-5-4\n* 新增文件日志记录器：`FileLogger`（用于支持持久化日志到文件）\n* 新增日志格式：`LogFormat`（用于支持多种的日志显示格式）\n* 新增函数：`LogX.format(logFormat)`（用于临时指定日志格式）\n* 完善注释说明\n* 优化配置方式（让Java与Kotlin的配置方式尽可能的一致）\n* 优化一些细节\n\n#### [查看更多版本日志](CHANGELOG.md)\n\n---\n\n![footer](https://jenly1314.github.io/page/footer.svg)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjenly1314%2FLogX","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjenly1314%2FLogX","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjenly1314%2FLogX/lists"}