Flutter Awesome Logger π
Lightweight debugging with floating logger, automatic API logging (using interceptor), Flutter general logging, and a beautiful UI for viewing logs
π Documentation β’ π Installation β’ π‘ Examples β’ π¨ Customization
π Table of Contents
- β¨ Features
- πΈ Screenshots
- π Getting Started
- π·οΈ AwesomeLoggerMixin & Scoped Logger
- π§ Configuration Options
- βοΈ Settings Modal
- π Advanced Usage
- π¨ Customization
- π€ Contributing
- π License
- π Issues & Support
- π Connect With Us
β¨ Features
| Feature | Description |
|---|---|
| π± Floating Logger Button | Always accessible debug button that floats over your app - drag to reposition, auto-snaps to edges |
| π Long Press Floating Button | Tap: Opens logger UI instantly β’ Long Press: Shows quick actions menu β’ Drag: Repositions button β’ Double Tap: Toggles pause/resume logging |
| π Automatic API Logging | Built-in Dio interceptor for seamless API logging - captures requests, responses, errors, and timing automatically |
| π± API Demo Page | Comprehensive demo page showcasing GET, POST, and error handling with real API calls and automatic logging |
| π¨ Unified Beautiful UI | Clean, modern interface with syntax highlighting - unified view for all logs, advanced filtering, and intuitive navigation |
| π Multiple Log Levels | Support for debug, info, warning, error, and verbose logs - color-coded with filtering and search capabilities |
| πΎ Smart Storage | Logs stored only when logger is enabled - conserves memory and respects privacy settings |
| π Source File Tracking | Easy Debugging: See exact file paths and line numbers for all logs - instantly identify where issues originate! |
| βΈοΈ Pause/Resume Logging | Temporarily pause all logging with visual indicators - useful for focusing on specific app sections |
| π Search & Filter | Easily find specific logs with advanced filtering - search by text, level, timestamp, or source file |
| π·οΈ Class-Based Filtering | Advanced filtering by class names, sources, and file paths with visual badges and unified clear controls |
| ποΈ Smart Filter Management | Universal "Clear All Filters" button and always-visible selected items - manage filters across all modes |
| π Filter Mode Indicators | Filter mode chips show badges indicating selected item counts for each category |
| π AwesomeLoggerMixin | Add with AwesomeLoggerMixin to any class for automatic source tracking - zero boilerplate! |
| π― Scoped Logger | Create scoped logger instances with logger.scoped('ClassName') for pre-configured source |
| π Dual View Filtering | Toggle between list and compact chip views for class selection with search capabilities |
| π― Simple Configuration | Single enabled property controls both UI and storage - async support for conditional initialization |
| βοΈ Settings Modal | Comprehensive runtime configuration via settings modal - adjust all logger options on-the-fly |
| π Circular Buffer | Configurable log replacement behavior - choose between replacing oldest logs or stopping when limit reached |
| π± Responsive Design | Works perfectly on all screen sizes - adaptive layouts for phones, tablets, and different orientations |
| π Smart Copy Options | Multiple copy options for logs: full logs, cURL commands, responses, and cURL+response combinations |
| π¦ Clean Bulk Exports | Filtered log exports focus on essential information - API logs show cURL and response only |
πΈ Screenshots
πΌοΈ App Screenshots Gallery
π Getting Started
Installation
π¦ Add to your pubspec.yaml
dependencies:
flutter_awesome_logger: ^latest_version
π Install the package
# Using Flutter CLI
flutter pub get
# Or using Dart CLI
dart pub get
π± Import in your Dart code
import 'package:flutter_awesome_logger/flutter_awesome_logger.dart';
Basic Usage
β‘ Easiest Setup (Just 2 Lines!)
The absolute simplest way to get started - just wrap your app:
import 'package:flutter/material.dart';
import 'package:flutter_awesome_logger/flutter_awesome_logger.dart';
// Global navigator key for navigation (required for logger history page)
final navigatorKey = GlobalKey<NavigatorState>();
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return FlutterAwesomeLogger(
navigatorKey: navigatorKey, // Required if logger history page does not open on floating button press
child: MaterialApp(
navigatorKey: navigatorKey,
home: const YourHomePage(),
),
);
}
}
That's it! π The logger is now active with default settings. You'll see:
- π± Floating logger button on your screen
- π Unified logger interface ready for all your logs
π API Demo Page (Advanced Example)
For a comprehensive demonstration of API logging capabilities, check out our example app's dedicated API demo page:
// Navigate to API demo page from your app
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const ApiDemoPage()),
);
What the API demo includes:
- β GET Requests - Fetch all users and individual users by ID
- β POST Requests - Create new users with sample data
- β Error Handling - Simulate and handle API errors (404, network issues)
- β Loading States - Beautiful loading indicators during requests
- β User Cards - Attractive display of user data with avatars and details
- β Auto-logging - Every request is automatically logged with full details
- β cURL Generation - Copy-paste ready cURL commands for testing
Features demonstrated:
- Real-time API logging with Dio interceptor
- Error state management and user feedback
- Professional UI with loading states and error displays
- Comprehensive user data model with JSON parsing
- Multiple HTTP methods (GET, POST) with proper error handling
π How to Get Logs in the Unified Interface
π API Logs
For HTTP requests and responses
To capture API logs in the unified logger interface, add the Dio interceptor:
Step 1: Add the interceptor to your Dio instance
import 'package:dio/dio.dart';
import 'package:flutter_awesome_logger/flutter_awesome_logger.dart';
final dio = Dio();
dio.interceptors.add(FlutterAwesomeLoggerDioInterceptor());
// Now all API calls are automatically logged!
final response = await dio.get('https://jsonplaceholder.typicode.com/users');
What you get:
- β Automatic capture - All requests and responses logged automatically
- β cURL generation - Copy-paste ready cURL commands for testing
- β Error handling - Network errors and HTTP errors captured
- β Performance timing - Request duration tracking
- β Advanced filtering - Filter by status code, method, or endpoint
- β Search functionality - Search through URLs, headers, and response content
π General Logs
For application logs and debugging
To capture general logs in the unified logger interface:
Step 1: Create a logger instance
Create a my_logger.dart file (or any name you prefer):
// my_logger.dart
import 'package:flutter_awesome_logger/flutter_awesome_logger.dart';
/// Global logger instance for use throughout the app.
/// Use this in files where you DON'T use AwesomeLoggerMixin.
final logger = FlutterAwesomeLogger.loggingUsingLogger;
Step 2: Use the logger throughout your app
import 'my_logger.dart';
class MyService {
void performOperation() {
// Debug information (development only)
logger.d('Starting complex operation with parameters: $params');
// General information (important events)
logger.i('User logged in successfully');
// Warnings (potential issues)
logger.w('API rate limit approaching: ${remaining} requests left');
// Errors (with full context)
try {
// Your code here
} catch (e, stackTrace) {
logger.e('Failed to process user data', error: e, stackTrace: stackTrace);
}
}
}
What you get:
- β Multiple log levels - DEBUG (grey), INFO (blue), WARNING (orange), ERROR (red)
- β Stack trace support - Full error context with file paths and line numbers
- β Source File Tracking - π Easy Debugging: See exact file paths and line numbers for instant issue identification - no more guessing where your code is logging from!
- β Advanced filtering - Filter by log level, source file, or search content
- β Export capabilities - Copy individual logs or export entire filtered sets
- β Real-time updates - Logs appear instantly as your app runs
β οΈ Release Build Limitations
π File Paths in Production/Release Builds
In debug mode, the logger automatically extracts file paths from stack traces to show you exactly where each log originates. However, in release/production builds, Flutter strips debug information (including stack traces) for performance and security reasons.
What you'll see:
- Debug mode:
./lib/pages/home_page.dart:42:10β - Release mode:
unknownβ οΈ
π‘ Solution: Use the source Parameter
To maintain source tracking in release builds, use the optional source parameter:
// Without source (works in debug, shows 'unknown' in release)
logger.d('Loading user data');
// With source (works in both debug AND release builds!)
logger.d('Loading user data', source: 'HomeScreen');
logger.i('User logged in successfully', source: 'AuthService');
logger.w('Cache miss detected', source: 'CacheManager');
logger.e('Failed to fetch data', error: e, source: 'ApiRepository');
π― Best Practice for Production Apps
Option 1: Using AwesomeLoggerMixin (Recommended)
import 'package:flutter_awesome_logger/flutter_awesome_logger.dart';
class UserRepository with AwesomeLoggerMixin {
// logger.d(), logger.i(), etc. automatically use 'UserRepository' as source!
Future<User> fetchUser(String id) async {
logger.d('Fetching user: $id'); // source: 'UserRepository'
try {
final user = await api.getUser(id);
logger.i('User fetched successfully'); // source: 'UserRepository'
return user;
} catch (e, stack) {
logger.e('Failed to fetch user', error: e, stackTrace: stack); // source: 'UserRepository'
rethrow;
}
}
}
Option 2: Using Scoped Logger
class UserRepository {
final _logger = logger.scoped('UserRepository');
// Or: late final _logger = logger.scoped(runtimeType.toString());
Future<User> fetchUser(String id) async {
_logger.d('Fetching user: $id'); // source: 'UserRepository'
// ...
}
}
Option 3: Manual source parameter
class UserRepository {
static const _source = 'UserRepository'; // Define once per class
Future<User> fetchUser(String id) async {
logger.d('Fetching user: $id', source: _source);
try {
final user = await api.getUser(id);
logger.i('User fetched successfully', source: _source);
return user;
} catch (e, stack) {
logger.e('Failed to fetch user', error: e, stackTrace: stack, source: _source);
rethrow;
}
}
}
π·οΈ Impact on Class Filtering
When file paths show as unknown in release builds:
- Classes button will appear grey (no classes available)
- Class filtering won't work since classes are extracted from file paths
Solution: Always use the source parameter in production apps to enable full filtering capabilities!
π·οΈ AwesomeLoggerMixin & Scoped Logger
π― Automatic Source Tracking for Classes
The easiest way to add class-based source tracking to all your logs. No more manually passing source to every log call!
π§ Option 1: AwesomeLoggerMixin (Recommended)
Simply add the mixin to your class - all logs will automatically use the class name as source:
import 'package:flutter_awesome_logger/flutter_awesome_logger.dart';
// Works with Cubits, Blocs, Services, Repositories, Widgets - any class!
class CubitAppConfig extends Cubit<StateAppConfig> with AwesomeLoggerMixin {
CubitAppConfig() : super(const StateAppConfig()) {
logger.d('Instance created, hashCode: $hashCode');
// β Logs with source: 'CubitAppConfig' automatically!
}
void loadConfig() {
logger.i('Loading config...'); // source: 'CubitAppConfig'
logger.w('Cache expired'); // source: 'CubitAppConfig'
}
void handleError(Object error, StackTrace stack) {
logger.e('Failed to load', error: error, stackTrace: stack);
// β source: 'CubitAppConfig'
}
}
How it works:
- The mixin provides a
loggergetter that returns aScopedLogger - Uses
runtimeType.toString()to automatically get the class name - The mixin's
loggershadows any imported globalloggerwithin the class - Works correctly with inheritance - subclasses get their own class name
π§ Option 2: Scoped Logger
For more control, create a scoped logger instance:
import 'package:flutter_awesome_logger/flutter_awesome_logger.dart';
class MyService {
// Option A: Hardcoded source name
final _logger = logger.scoped('MyService');
// Option B: Using runtimeType (use late final)
// late final _logger = logger.scoped(runtimeType.toString());
void doSomething() {
_logger.d('Doing something'); // source: 'MyService'
_logger.i('Task completed'); // source: 'MyService'
}
}
π Comparison Table
| Approach | Pros | Use When |
|---|---|---|
AwesomeLoggerMixin |
Zero boilerplate, auto class name | Most cases - just add with AwesomeLoggerMixin |
logger.scoped() |
Explicit control, custom naming | Custom source names, or can't use mixin |
source: parameter |
One-off overrides | Occasional different source needed |
π‘ Tips
- No Import Conflicts: Don't import
my_logger.dartin files where you useAwesomeLoggerMixin. The mixin provides its ownloggergetter. - Use
logger.source: Access the source name withlogger.source(returns the class name) - Production Ready: Uses
runtimeTypewhich is available in both debug and release builds - Filtering: All logs with source are filterable in the logger UI using the Classes filter
π Import Guide
| File Type | What to Import |
|---|---|
Files with AwesomeLoggerMixin |
Only import 'package:flutter_awesome_logger/flutter_awesome_logger.dart'; |
| Files without mixin | import 'my_logger.dart'; to use global logger |
π·οΈ Class-Based Filtering
π― Focus on Specific App Components
Class filtering helps you narrow down logs to specific parts of your application by filtering based on class names extracted from file paths.
π±οΈ How to Use Class Filtering
- Open Logger History: Tap the floating logger button to access the unified logger interface
- Click Classes Button: Look for the "Classes" button in the filter section (appears purple when classes are available, grey when none exist)
- Select Classes: Choose from available class names in the bottom sheet
- View Toggle: Switch between list view and compact chip view using the toggle button
- Search Classes: Use the search field to quickly find specific classes
- Apply Filters: Selected classes will be highlighted and logs filtered accordingly
π¨ Visual Indicators
- Purple Button: Classes are available for filtering
- Grey Button: No classes found in current logs (still clickable to learn about the feature)
- Selected Classes: Purple background with white text and count badges
- Compact View: Space-efficient chip layout for quick selection
π‘ What Classes Are Available?
- Automatic Detection: Classes are extracted from general log file paths
- File-Based: Class names come from
.dartfile names (e.g.,home_page.dartβhome_page) - Real-time Updates: Available classes update as you use different parts of your app
- Smart Filtering: Only shows classes that have generated logs
π Advanced Class Filtering
// Programmatic access to class filtering
final availableClasses = FlutterAwesomeLogger.getAvailableClasses();
final classCounts = FlutterAwesomeLogger.getClassCounts();
// Classes are automatically extracted from logs like:
logger.d('User tapped login button'); // Creates 'my_widget' class filter
π§ Configuration Options
βοΈ Flexible Configuration System
ποΈ FlutterAwesomeLogger Configuration
The enabled parameter supports both synchronous and asynchronous initialization:
|
π’ Immediate Enable
Logger starts immediately |
π΄ Immediate Disable
Logger is disabled |
β³ Async Enable
Waits for Future resolution |
π AwesomeLoggerConfig
Core logging behavior configuration
| Property | Type | Default | Description |
|---|---|---|---|
maxLogEntries |
int |
1000 |
Maximum number of log entries to keep in memory |
showFilePaths |
bool |
true |
Display file paths in console output |
showEmojis |
bool |
true |
Show emojis in console output for better readability |
useColors |
bool |
true |
Enable colored console output |
stackTraceLines |
int |
0 |
Number of stack trace lines to display |
enableCircularBuffer |
bool |
true |
Enable circular buffer - replace oldest logs when limit reached, or stop logging |
const AwesomeLoggerConfig({
int maxLogEntries = 1000,
bool showFilePaths = true,
bool showEmojis = true,
bool useColors = true,
int stackTraceLines = 0,
bool enableCircularBuffer = true,
});
π¨ FloatingLoggerConfig
Floating button UI and behavior configuration
| Property | Type | Default | Description |
|---|---|---|---|
backgroundColor |
Color |
Colors.deepPurple |
Background color of the floating button |
icon |
IconData |
Icons.developer_mode |
Icon displayed on the floating button |
showCount |
bool |
true |
Display log count badge on button |
enableGestures |
bool |
true |
Enable drag gestures for repositioning |
autoSnapToEdges |
bool |
true |
Automatically snap button to screen edges |
size |
double |
60.0 |
Size of the floating button |
const FloatingLoggerConfig({
Color backgroundColor = Colors.deepPurple,
IconData icon = Icons.developer_mode,
bool showCount = true,
bool enableGestures = true,
bool autoSnapToEdges = true,
double size = 60.0,
});
π Advanced Usage
Accessing Log History
// Get all stored logs
final logs = FlutterAwesomeLogger.getLogs();
// Get logs by level
final errorLogs = FlutterAwesomeLogger.getLogsByLevel('ERROR');
// Get recent logs
final recentLogs = FlutterAwesomeLogger.getRecentLogs(
duration: Duration(minutes: 10),
);
// Clear all logs
FlutterAwesomeLogger.clearLogs();
// Export logs as formatted text
String exportedLogs = FlutterAwesomeLogger.exportLogs();
Programmatically Show Logger UI
// Show the unified logger history page
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const AwesomeLoggerHistoryPage(),
),
);
Pause/Resume Logging
// Pause all logging (both console and storage)
FlutterAwesomeLogger.setPauseLogging(true);
// Resume logging
FlutterAwesomeLogger.setPauseLogging(false);
// Check if logging is paused
bool isPaused = FlutterAwesomeLogger.isPaused;
Control Floating Logger Visibility
// Check if floating logger is visible
bool isVisible = FlutterAwesomeLogger.isVisible();
// Show/hide the floating logger
FlutterAwesomeLogger.setVisible(true); // Show
FlutterAwesomeLogger.setVisible(false); // Hide
// Toggle visibility
FlutterAwesomeLogger.toggleVisibility();
Manage API Logs
// Get all API logs
final apiLogs = FlutterAwesomeLogger.getApiLogs();
// Get API logs by type
final successLogs = FlutterAwesomeLogger.getApiLogsByType(ApiLogType.success);
final errorLogs = FlutterAwesomeLogger.getApiLogsByType(ApiLogType.serverError);
// Clear API logs
FlutterAwesomeLogger.clearApiLogs();
βοΈ Settings Modal
ποΈ Runtime Configuration
The settings modal provides comprehensive runtime control over all logger behavior
π±οΈ Accessing Settings
- App Bar Icon: Tap the settings icon (βοΈ) in the logger history page app bar
- Modal Interface: Clean bottom sheet with organized configuration sections
π§ Available Settings
| Setting | Description |
|---|---|
| π Max Log Entries | Real-time adjustment of maximum log entries limit. Changes take effect immediately. |
| π Circular Buffer |
ON (default): Automatically replaces oldest logs when limit reached OFF: Stops logging completely when limit reached |
| π Show File Paths | Toggle display of file paths and line numbers in console output |
| π Show Emojis | Toggle emoji indicators in console logs for better readability |
| π¨ Use Colors | Toggle color coding for different log levels in console output |
| π Current Stats | Real-time display of currently stored log count |
π‘ Usage Tips
- Immediate Changes: All settings take effect instantly - no app restart required
- Mobile Friendly: Modal handles keyboard input and different screen sizes
- Visual Feedback: Current behavior is clearly described for each setting
- Live Stats: See how many logs are currently stored as you adjust limits
π± Example Configuration
// Initial configuration
loggerConfig: const AwesomeLoggerConfig(
maxLogEntries: 500,
enableCircularBuffer: true, // Replace oldest logs
showFilePaths: true,
showEmojis: true,
useColors: true,
),
// Runtime changes via settings modal:
// - Change maxLogEntries to 1000
// - Toggle enableCircularBuffer to false
// - Turn off showEmojis
// All changes apply immediately!
π¨ Customization
The logger UI is highly customizable. You can:
- Change colors and themes
- Customize the floating button appearance
- Configure log display formats
- Add custom filters and search options
- Pause/resume logging as needed
- Control logging behavior with simple configuration
π€ Contributing
We welcome contributions!
Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
π Issues & Support
π Bug ReportsFound a bug? Let us know! |
π‘ Feature RequestsHave an idea? Share it! |
π¬ DiscussionsJoin the conversation! |
π Connect With Us
π§ Email |
π¦ Twitter |
π¬ Discord |
β Show Your Support
If this package helped you, please consider giving it a β on GitHub!
Made with β€οΈ by codeastartup01dev