✨ Features
Flexible Configuration
- Customizable log levels and filtering
- Global tag prefixes for organized logging
- Thread-safe operations
- Enable/disable logging globally
Multiple Destinations
- Logcat - Standard Android logging
- File Logging - Persistent file storage
- Custom Destinations - Extensible interface
Pretty Printing
- Beautiful JSON formatting
- XML pretty printing
- Structured log formatting
- Timestamp and thread info
Smart File Management
- Automatic log rotation
- Size-based file clearing
- Organized directory structure
- Crash-safe file operations
🚀 Installation
Kotlin DSL
Groovy
//settings.gradle dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { mavenCentral() maven { url = URI("https://jitpack.io") } // Add this } } // App module dependencies { implementation("com.github.goodluck3301:FlexLogger:flexlogger-1.1") }
//settings.gradle dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { mavenCentral() maven { url 'https://jitpack.io' } // Add this } } // App module dependencies { implementation 'com.github.goodluck3301:FlexLogger:flexlogger-1.1' }
⚡ Quick Start
1. Initialize in your Application class
class MyApplication : Application() { override fun onCreate() { super.onCreate() FlexLogger.init { enabled = true globalTagPrefix = "MyApp" minLevel = LogLevel.DEBUG showTimestamp = true showThreadInfo = true // Add destinations logcat() file( context = this@MyApplication, fileName = "app_log.txt", maxFileSizeMb = 5 ) } } }
2. Register in AndroidManifest.xml
<application android:name=".MyApplication" ... > </application>
3. Start logging!
class MainActivity : AppCompatActivity() { private val TAG = "MainActivity" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Basic logging log_v(TAG, "Activity created successfully") log_d(TAG, "Debug information: ${someVariable}") // Error logging with exception try { riskyOperation() } catch (e: Exception) { log_e(TAG, "Operation failed") } // Pretty print JSON log_json(TAG, """{"user": "John", "id": 123}""") } }
📚 Documentation
Log Levels
Level | Function | Description |
---|---|---|
VERBOSE |
log_v() |
Detailed information for debugging |
DEBUG |
log_d() |
Debug information for development |
INFO |
log_i() |
General information messages |
WARN |
log_w() |
Warning messages for potential issues |
ERROR |
log_e() |
Error messages for failures |
ASSERT |
log_wtf() |
Critical errors that should never happen |
💡 Examples
Basic Usage
class NetworkManager { private val TAG = "NetworkManager" suspend fun fetchData(): Result { log_i(TAG, "Starting data fetch operation" ) return try { val response = apiService.getData() log_json(TAG, LogLevel.DEBUG, response.body()) Result.success(response.data) } catch (e: Exception) { log_e(TAG, e, "Failed to fetch data from API") Result.failure(e) } } }
Custom Log Destination
class RemoteLogDestination(private val apiEndpoint: String) : LogDestination { override val id = "remote_logger" override fun send(logMessage: LogMessage, formattedMessage: String) { // Send logs to remote server if (logMessage.level >= LogLevel.ERROR) { sendToRemoteServer(formattedMessage) } } private fun sendToRemoteServer(message: String) { // Implementation for remote logging } } // Usage in configuration FlexLogger.init { addDestination(RemoteLogDestination("https://api.example.com/logs")) }
🏗️ Architecture
Application
log_i(...)
log_e(...)
log_json()
log_i(...)
log_e(...)
log_json()
→
FlexLogger
LogMessage
Processing
LogMessage
Processing
→
Destinations
Logcat
File
Custom
Logcat
File
Custom
🎯 Best Practices
✅ Do's
- Initialize early: Set up FlexLogger in your Application's onCreate()
- Use meaningful tags: Create constants for tags in each class
- Leverage lazy evaluation: Use lambda functions for expensive string operations
- Log at appropriate levels: Use DEBUG for development, INFO for important events
- Handle exceptions: Always log exceptions with context
❌ Don'ts
- Don't log sensitive data: Avoid logging passwords, tokens, or personal information
- Don't over-log: Excessive logging can impact performance
- Don't forget to disable: Consider disabling verbose logging in production
- Don't ignore file sizes: Monitor log file sizes to prevent storage issues
🔒 Production Configuration
FlexLogger.init { enabled = BuildConfig.DEBUG // Disable in release builds minLevel = LogLevel.INFO // Only log important messages showThreadInfo = false // Reduce log verbosity if (BuildConfig.DEBUG) { logcat() file(context = this@MyApplication, maxFileSizeMb = 5) } }
📜 Changelog
v1.1 2025
Enhanced logging capabilities and stability improvements
- Features:
- Added global uncaught exception handler to log crashes (Levon, 03.07.2025)
- Safely trim log file using temp file to prevent data loss (Levon, 02.07.2025)
- Validate 'maxFileSizeMb' does not exceed allowed limit (Levon, 02.07.2025)
- Make log file path dynamic (Levon, 28.06.2025)
- Refactors:
- Deprecated old flexLog* functions in favor of log_* versions (Levon, 02.07.2025)
- Renamed log functions to use log_ prefix for easier use (Levon, 02.07.2025)
- Extracted and organized utility functions into helpers folder (Levon, 01.07.2025)
- Split log writing and trimming into separate functions for clarity and performance (Levon, 01.07.2025)
- Tests:
- Added concurrent logging test for 1MB log file size overflow (Levon, 02.07.2025)
- Added concurrency test to verify thread-safe logging behavior (Levon, 01.07.2025)
- Added unit tests for FlexLogger (Levon, 01.07.2025)
- Added unit tests for FileDestination class (Levon, 30.06.2025)
- Added file logging and log size limit tests for FlexLogger (Levon, 29.06.2025)
- Added basic unit tests (Levon, 28.06.2025)
- Chores:
- Added testing dependencies (Levon, 28.06.2025)
v1.0.0 June 15, 2025
Initial release of FlexLogger
- Added core logging functionality with Logcat support
- Implemented file logging with rotation
- Introduced pretty printing for JSON and XML
- Added customizable configuration via Kotlin DSL