flutter_awesome_logger 4.0.0
flutter_awesome_logger: ^4.0.0 copied to clipboard
Lightweight debugging with floating logger, automatic API logging (using interceptor), Flutter general logging, class-based filtering, scoped logger mixin, smart copy options, and a beautiful UI for v [...]
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 #
π 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 Reports #Found a bug? Let us know! |
π‘ Feature Requests #Have an idea? Share it! |
π¬ Discussions #Join the conversation! |