orhanobut/logger
✔️ Simple, pretty and powerful logger for android
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓10 active contributors
- ✓Distributed ownership (top contributor 37% of recent commits)
- ✓Apache-2.0 licensed
Show all 6 evidence items →Show less
- ✓CI configured
- ✓Tests present
- ⚠Stale — last commit 4y ago
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/orhanobut/logger)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/orhanobut/logger on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: orhanobut/logger
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/orhanobut/logger shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- 10 active contributors
- Distributed ownership (top contributor 37% of recent commits)
- Apache-2.0 licensed
- CI configured
- Tests present
- ⚠ Stale — last commit 4y ago
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live orhanobut/logger
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/orhanobut/logger.
What it runs against: a local clone of orhanobut/logger — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in orhanobut/logger | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | Last commit ≤ 1362 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of orhanobut/logger. If you don't
# have one yet, run these first:
#
# git clone https://github.com/orhanobut/logger.git
# cd logger
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of orhanobut/logger and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "orhanobut/logger(\\.git)?\\b" \\
&& ok "origin remote is orhanobut/logger" \\
|| miss "origin remote is not orhanobut/logger (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 1362 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~1332d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/orhanobut/logger"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
orhanobut/logger is a lightweight Android logging library that provides pretty-printed, thread-aware log output to logcat with optional disk persistence. It supports formatted strings, collections, JSON/XML parsing, and pluggable format strategies (PrettyFormatStrategy, CsvFormatStrategy) to customize how logs appear — solving the verbosity and readability problems of raw Android Log calls. Single-module structure: logger/src/main/java/com/orhanobut/logger/ contains the core architecture with LoggerPrinter as the main facade, pluggable LogAdapter/LogStrategy interfaces for output targets (AndroidLogAdapter, DiskLogAdapter), and FormatStrategy implementations (PrettyFormatStrategy, CsvFormatStrategy) for customizing message layout. Tests are colocated in logger/src/test/java/ in Kotlin.
👥Who it's for
Android developers who need clean, readable debug output during development and want to optionally persist logs to disk for crash reports or analytics without manually formatting or managing log file I/O.
🌱Maturity & risk
Mature and production-ready. The library is small (18 KB, ~200 methods), has been on Android Arsenal, has a solid test suite in Kotlin (AndroidLogAdapterTest.kt, DiskLogAdapterTest.kt, CsvFormatStrategyTest.kt), uses Travis CI for builds, and targets Android API 28. However, repo activity appears dormant — no recent commits visible in the provided metadata, though version 2.2.0 is published.
Low risk for maintenance. The library has minimal dependencies (only org.json:json:20160810 for JSON parsing), no external service requirements, and a stable API. Main risk is single-maintainer model (orhanobut) with no visible recent activity, meaning critical bugs or Android compatibility issues may not be addressed quickly. The minSdkVersion of 8 is outdated for modern Android development (min should be ≥21).
Active areas of work
Based on the metadata, no active development is evident. The repo appears to be in maintenance mode — no open PRs, recent commits, or milestone activity are visible. The last documented version is 2.2.0.
🚀Get running
git clone https://github.com/orhanobut/logger.git && cd logger && ./gradlew build
Daily commands: ./gradlew build && ./gradlew test
🗺️Map of the codebase
- logger/src/main/java/com/orhanobut/logger/Logger.java: Public static facade API; all library calls route through this entry point
- logger/src/main/java/com/orhanobut/logger/LoggerPrinter.java: Core implementation of the Printer interface; handles routing logs to all registered adapters and manages the stack-based method call tracking
- logger/src/main/java/com/orhanobut/logger/PrettyFormatStrategy.java: Default human-readable formatter; implements the pretty-printing with thread info, method call stack, and borders
- logger/src/main/java/com/orhanobut/logger/AndroidLogAdapter.java: Logcat output adapter; bridges formatted logs to Android's Log.d/e/i/w/v/wtf; includes isLoggable filtering
- logger/src/main/java/com/orhanobut/logger/DiskLogAdapter.java: File persistence adapter; enables saving logs to device storage using DiskLogStrategy
- logger/src/main/java/com/orhanobut/logger/CsvFormatStrategy.java: CSV-formatted output strategy for structured log storage; allows custom tags and file-based logging
- logger/src/main/java/com/orhanobut/logger/FormatStrategy.java: Interface contract for all format strategies; defines format(priority, tag, message) method for custom implementations
- logger/build.gradle: Library build config; defines version, dependencies (json, supportAnnotations, kotlin), and publication settings
🛠️How to make changes
Core logging logic: modify logger/src/main/java/com/orhanobut/logger/LoggerPrinter.java. Add output formats: create new class extending FormatStrategy in logger/src/main/java/com/orhanobut/logger/. Add output targets: create new class extending LogAdapter. Add tests: corresponding .kt test file in logger/src/test/java/com.orhanobut.logger/. Follow checkstyle.xml rules (enforced at build time).
🪤Traps & gotchas
The Logger class uses a static List<LogAdapter> via addLogAdapter(); calling Logger methods before any adapter is added will silently do nothing (no null checks, no warnings). The methodOffset parameter in PrettyFormatStrategy skips internal library frames but hardcoded assumptions about stack depth may break if the call chain changes. DiskLogAdapter requires file write permissions but the repo does not document required Android manifest permissions. minSdkVersion=8 is incompatible with modern AndroidX libraries (repo uses androidx.annotation:annotation:1.0.0 anyway). JSON/XML logging methods (Logger.json(), Logger.xml()) only output at DEBUG level — cannot be changed via FormatStrategy.
💡Concepts to learn
- Strategy Pattern (FormatStrategy, LogStrategy) — Core design allowing users to swap logging output targets and message formatters at runtime without changing Logger API; enables PrettyFormatStrategy vs CsvFormatStrategy and AndroidLogAdapter vs DiskLogAdapter interchangeability
- Stack Trace Introspection & methodOffset — Logger uses reflection (Thread.currentThread().getStackTrace()) to find the caller's method name and line number, then skips methodOffset frames to hide internal library calls; understanding this prevents off-by-one errors in custom format strategies
- Adapter Pattern (LogAdapter as bridge to LogStrategy) — LogAdapter wraps FormatStrategy + LogStrategy separation; allows formatting logic to remain independent from output mechanism, enabling disk/logcat/network outputs with same format
- Facade Pattern (Logger static API) — Logger class provides a simple static entry point (Logger.d(), Logger.e()) while hiding LoggerPrinter, LogAdapter list, and routing complexity; reduces client code boilerplate
- Structured Logging (CSV format strategy) — CsvFormatStrategy outputs logs as parseable CSV with timestamp, level, tag, message columns; enables automated log aggregation, grep'ability, and machine analysis vs unstructured pretty-printed output
- Lazy String Formatting (varargs support) — Logger.d(format, arg1, arg2) defers String.format() call until after isLoggable() check; avoids expensive string allocation when logs are disabled, a micro-optimization critical for performance-sensitive apps
- Thread-aware logging (showThreadInfo flag) — PrettyFormatStrategy can include current thread name in each log line (Thread.currentThread().getName()); essential for debugging race conditions and threading issues in concurrent Android code
🔗Related repos
JakeWharton/timber— Industry-standard Android logger with tree-based API, automatic tag resolution, and better lifecycle-aware crash logging; direct competitor with more active maintenancefacebook/stetho— Facebook's Chrome DevTools bridge for Android; complements logger by adding interactive inspection of logs, network, and database during developmentsquare/leakcanary— Memory leak detector library that uses logging internally; often used alongside loggers to diagnose app issuesorhanobut/debugdrawer— Sibling library by the same author; provides in-app overlay debug drawer that displays logs, network calls, and app info in real timeacra/acra— Crash reporting framework for Android that integrates with loggers to capture crash context and send to backend services
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add integration tests for DiskLogAdapter with real file I/O scenarios
The test suite has DiskLogAdapterTest.kt and DiskLogStrategyTest.kt, but based on the file structure, there are no tests covering edge cases like disk full, permission errors, concurrent writes, or file rotation scenarios. This is critical for a logging library where data persistence is a key feature.
- [ ] Review logger/src/test/java/com.orhanobut.logger/DiskLogAdapterTest.kt and DiskLogStrategyTest.kt to identify missing edge case coverage
- [ ] Add test cases for: disk space exhaustion, file permission denial, concurrent logging from multiple threads, and log file rotation limits
- [ ] Add test utilities to simulate file system errors using Robolectric's shadow file system
- [ ] Ensure tests validate graceful degradation when disk logging fails
Add GitHub Actions workflow to replace Travis CI and test across API levels
The repo uses .travis.yml for CI, but there's no GitHub Actions workflow. GitHub Actions integrates better with GitHub's native tooling. Additionally, the minSdkVersion is 8 but there's no evidence of testing across multiple Android API levels (API 21, 28, 30+), which is important for a logging library used in diverse production apps.
- [ ] Create .github/workflows/android-build.yml with matrix testing for compileSdkVersion 28, 29, 30, and 31
- [ ] Configure the workflow to run unit tests, Checkstyle validation, and build the sample app
- [ ] Add test coverage reporting step to the workflow
- [ ] Consider deprecating .travis.yml or updating it to reference the new GitHub Actions workflow
Add comprehensive documentation for FormatStrategy and LogStrategy extension points with examples
The codebase has FormatStrategy.java and LogStrategy.java as extension points, plus implementations like PrettyFormatStrategy, CsvFormatStrategy, LogcatLogStrategy, and DiskLogStrategy. However, the README snippet doesn't show documentation for creating custom implementations. New contributors and users need clear guidance on extending the library.
- [ ] Create a new CUSTOMIZATION.md or EXTENSION.md guide in the repo root
- [ ] Document the FormatStrategy interface with a concrete example (e.g., JSONFormatStrategy or XMLFormatStrategy) that contributors can reference
- [ ] Document the LogStrategy interface with a custom example (e.g., RemoteLoggingStrategy or DatabaseLogStrategy)
- [ ] Add code snippets showing how to initialize Logger with custom strategies, referencing sample/src/main/java/com/orhanobut/sample/MainActivity.java as a starting point for a sample implementation
🌿Good first issues
- Add unit tests for Utils.java — currently no test file exists for the utility methods (getStackTraceElement, methodCount, formatStrings). Create logger/src/test/java/com.orhanobut.logger/UtilsTest.kt with tests for string formatting, stack frame extraction, and edge cases.
- Document and add integration tests for DiskLogAdapter file I/O — the DiskLogStrategy.kt test exists but doesn't verify actual file creation, permissions, or rotation behavior. Add tests that verify logs are actually written to disk and readable after app restart.
- Raise minSdkVersion from 8 to 21 and update README with deprecation notice — Android API 8 (Froyo, 2010) is no longer viable; the build matrix should target modern APIs. This unblocks modern Android library adoption and simplifies the codebase.
⭐Top contributors
Click to expand
Top contributors
- [@Orhan Obut](https://github.com/Orhan Obut) — 37 commits
- @orhanobut — 34 commits
- @oobut — 13 commits
- @svenjacobs — 7 commits
- @hrskrs — 3 commits
📝Recent commits
Click to expand
Recent commits
c64a72c— Merge pull request #249 from balajisunku-halodoc/androidx_support (orhanobut)66032ff— Migrated to AndroidX (balaji-sunku)4a85b78— Rename ISSUE_TEMPLATE.md to .github/ISSUE_TEMPLATE.md (orhanobut)1c51e3a— Create ISSUE_TEMPLATE.md (orhanobut)ab3ce9e— Merge pull request #179 from orhanobut/update-mockito (orhanobut)a48cb79— Update mockito (oobut)d11868f— Merge pull request #178 from orhanobut/update-tests (orhanobut)72fa77b— Update project code style (oobut)c42b675— Convert test classes to kotlin (oobut)b12c070— Remove redundant Robolectric config (oobut)
🔒Security observations
The codebase has significant security concerns primarily related to outdated dependencies and build tools. The project uses dependencies and build plugins from 2016-2018, which are well beyond their support lifecycle and likely contain known vulnerabilities. The extremely low minSdkVersion (8) further limits access to modern security APIs. Immediate action is required to update Gradle, Kotlin, and all test dependencies to current versions. Additionally, the use of deprecated repositories (jcenter) should be addressed for future maintenance stability. The logger library itself (based on file structure) appears to be a logging utility with no obvious injection vulnerabilities, but the build infrastructure requires urgent modernization.
- High · Outdated Gradle Build Plugin —
build.gradle (buildscript dependencies). The project uses Android Gradle Plugin version 3.2.0, which was released in September 2018 and is no longer supported. This version may contain known security vulnerabilities and lacks critical security patches. Fix: Update to a current version of the Android Gradle Plugin (e.g., 7.x or 8.x). Run 'gradle wrapper --gradle-version=<latest-version>' to update. - High · Outdated Kotlin Compiler —
build.gradle (ext.kotlinVersion). Kotlin version 1.2.51 (from 2018) is extremely outdated and likely contains security vulnerabilities. Current stable versions are 1.8.x and later. Fix: Update Kotlin to a current LTS or stable version (minimum 1.8.x). Update 'ext.kotlinVersion' to '1.8.0' or later. - High · Outdated Test Dependencies with Known Vulnerabilities —
build.gradle (ext.deps). The project uses Robolectric 3.3 (2016), Mockito 2.8.9 (2017), and org.json 20160810 (2016). These versions contain known security vulnerabilities and compatibility issues. Fix: Update to current versions: Robolectric 4.10.x or later, Mockito 5.x or later, org.json 20230227 or later. - Medium · Outdated JUnit Dependency —
build.gradle (ext.deps - junit). JUnit 4.12 (2014) is outdated. Consider upgrading to JUnit 4.13.x for security patches, or migrate to JUnit 5.x. Fix: Update JUnit to version 4.13.2 or migrate to JUnit 5.x (e.g., 5.9.2). - Medium · Low minSdkVersion May Limit Security Features —
build.gradle (ext.minSdkVersion). The project targets Android minSdkVersion 8, which is from 2009. This severely limits the availability of modern security APIs and best practices. Fix: Consider increasing minSdkVersion to at least 21 (Android 5.0) or higher to ensure compatibility with modern security standards. The current Android minimum is API 21. - Low · Deprecated Google Repository —
build.gradle (allprojects repositories). The build file uses 'google()' repository which is correct, but 'jcenter()' was sunset by JFrog in 2021 and should be replaced with 'mavenCentral()' or other active repositories. Fix: Replace 'jcenter()' with 'mavenCentral()' in the repositories block to ensure future dependency resolution stability. - Low · Missing Security Linting Configuration —
build.gradle and gradle configuration. No Android Lint security checks or OWASP Mobile Security Testing Guide (MSTG) configurations are present in the build configuration. Fix: Add lintOptions to catch security issues at compile time. Example: enable specific lint checks like 'MissingPermission', 'UnsecureProtocol', etc.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.