debug_bubble 0.1.1
debug_bubble: ^0.1.1 copied to clipboard
A reusable Flutter debugging toolkit with an in-app floating log viewer and error dashboard.
debug_bubble #
A high-performance in-app diagnostic toolkit and floating log viewer for Flutter applications.
debug_bubble provides a non-intrusive floating diagnostic bubble that expands into a full-featured in-app dashboard. Designed for mobile, tablet, desktop, and web, it enables real-time log streaming, full-text searching, JSON payload inspection, stack trace visualization, and automatic unhandled error capture with zero third-party runtime dependencies.
Features #
- Floating Diagnostic Bubble: Free-floating overlay that automatically snaps to display edges and reflects live error counters.
- Real-Time Log Stream: Low-latency log viewer with debounced filtering, severity filtering chips, and smooth auto-scrolling.
- Inline Entry Details: Inspect messages, error types, collapsible monospace stack traces, metadata tables, and pretty-printed JSON payloads.
- Dedicated Errors Tab: Instant isolated view for investigating high-severity (
errorandcritical) issues. - Toolkit Diagnostics (Info Tab): Real-time monitoring of session state, build mode, ring buffer capacity, and error-hook health.
- Automatic Crash Capture: Integrates with
FlutterError.onErrorandPlatformDispatcher.onErrorwith re-entrancy protection. - Data Privacy & Redaction: Configurable key and token normalization to redact sensitive credentials (passwords, tokens, API keys) alongside regex pattern scanning.
- Memory & Resource Bounded: Implements a fixed-capacity ring buffer (default 1,000 entries) and payload depth caps to prevent memory leaks.
- Zero Overhead in Release: The toolkit is inert in release mode (
kReleaseMode), ensuring zero CPU or memory footprint in production.
Screenshots #
| Floating Bubble Overlay | Real-Time Dashboard | Error & Crash Stream | Detailed Stack Trace |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
IDE Terminal Console Logging #
Getting Started #
Installation #
Add debug_bubble to your pubspec.yaml:
dependencies:
flutter:
sdk: flutter
debug_bubble: ^0.1.1
Alternatively, run:
flutter pub add debug_bubble
Basic Initialization #
Initialize the toolkit in your main() before executing runApp:
import 'package:debug_bubble/debug_bubble.dart';
import 'package:flutter/material.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
DebugLog.init(
const DebugBubbleConfig(
captureUncaughtErrors: true,
consoleOutput: true,
),
);
runApp(const MyApp());
}
Full Configuration Setup #
For production applications requiring custom data redaction, theme branding, custom export destinations, or adjusted buffer capacities:
import 'package:debug_bubble/debug_bubble.dart';
import 'package:flutter/material.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
DebugLog.init(
DebugBubbleConfig(
// Master switch and ring buffer capacity
enabled: true,
maxEntries: 1000,
minLevel: DebugLogLevel.debug,
// Console logging with ANSI severity colors
consoleOutput: true,
// Automatic uncaught framework and platform crash interception
captureUncaughtErrors: true,
// Viewport docking alignment for the floating bubble
initialBubbleAlignment: Alignment.centerRight,
// Sensitive data masking rules
redaction: DebugRedactionConfig(
enabled: true,
sensitiveKeys: {
...DebugRedactionConfig.defaultSensitiveKeys,
'token',
'secret',
'apiKey',
},
sensitiveKeyTokens: {
...DebugRedactionConfig.defaultSensitiveKeyTokens,
'pin',
'cvv',
},
valuePatterns: [
RegExp(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'), // Emails
RegExp(r'\b(?:\d{4}[ -]?){3}\d{4}\b'), // Payment card numbers
],
replacement: '[REDACTED]',
),
// Custom theme and severity badge palette
theme: const DebugBubbleTheme(
mode: ThemeMode.system,
bubbleColor: Color(0xFF1E1E24),
bubbleIconColor: Colors.white,
levelColors: {
DebugLogLevel.critical: Color(0xFFBF5AF2),
DebugLogLevel.error: Color(0xFFFF453A),
},
),
// Optional export callback (e.g., upload to backend or save to disk)
onExport: (String jsonPayload) async {
// await RemoteCrashReporter.upload(jsonPayload);
},
),
);
runApp(const MyApp());
}
Dashboard Setup #
Attach DebugBubble to your root application widget via MaterialApp.builder:
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Application',
builder: (context, child) => DebugBubble(
child: child ?? const SizedBox.shrink(),
),
home: const HomeScreen(),
);
}
}
Declarative Routing (go_router)
When using declarative routers like go_router or auto_route, wrap the root builder inside MaterialApp.router. Route redirects and navigator state changes will operate independently without dismissing the dashboard layer:
MaterialApp.router(
routerConfig: appRouter,
builder: (context, child) => DebugBubble(
child: child ?? const SizedBox.shrink(),
),
);
API Reference #
Logging Methods (DebugLog) #
The static DebugLog facade emits structured entries into the bounded memory store and terminal console:
| Method | Console ANSI Color | UI Badge Color | Supported Parameters | Intended Use |
|---|---|---|---|---|
DebugLog.trace() |
Gray (\x1B[90m) |
⚪ #8E8E93 |
message, tag, subTag, metadata, json |
Fine-grained verbose diagnostics, iterations, or low-level values. |
DebugLog.debug() |
Cyan (\x1B[36m) |
🩵 #64D2FF |
message, tag, subTag, metadata, json |
Development-phase state transitions and component lifecycles. |
DebugLog.info() |
Blue (\x1B[34m) |
🔵 #0A84FF |
message, tag, subTag, metadata, json |
Standard operational milestones (e.g., page navigation, user actions). |
DebugLog.success() |
Green (\x1B[32m) |
🟢 #30D158 |
message, tag, subTag, metadata, json |
Successful operational outcomes (e.g., API 200 OK, sync completion). |
DebugLog.warning() |
Yellow (\x1B[33m) |
🟠 #FF9F0A |
message, tag, subTag, metadata, json |
Non-fatal warnings (e.g., degraded connectivity, cache evictions). |
DebugLog.error() |
Red (\x1B[31m) |
🔴 #FF453A |
message, tag, subTag, error, stackTrace, metadata, json |
Caught exceptions, failed network calls, or validation failures. |
DebugLog.critical() |
Magenta (\x1B[35m) |
🟣 #BF5AF2 |
message, tag, subTag, error, stackTrace, metadata, json |
Critical subsystem failures, corrupt state, or unhandled errors. |
Parameter Descriptions:
message(String, required): The log description.tag(String?, optional): Top-level architectural domain (e.g.,'Network','Auth').subTag(String?, optional): Secondary sub-domain or endpoint (e.g.,'Login','UserSync').error(Object?, optional): Captured error or exception instance.stackTrace(StackTrace?, optional): Associated execution stack trace.metadata(Map<String, Object?>?, optional): Arbitrary structured key-value pairs.json(Object?, optional): JSON-serializable map, list, or primitive payload.
Toolkit Configuration (DebugBubbleConfig) #
Passed to DebugLog.init() to configure engine limits and behavior:
| Property | Type | Default Value | Description |
|---|---|---|---|
enabled |
bool |
true |
Master activation switch. Package is completely inert when false or in release mode. |
minLevel |
DebugLogLevel |
DebugLogLevel.debug |
Minimum severity level accepted by the ingestion pipeline. |
maxEntries |
int |
1000 |
Capacity of the memory ring buffer. Oldest entries are discarded when exceeded. |
consoleOutput |
bool |
true |
Whether to write color-formatted entries to standard output. |
captureUncaughtErrors |
bool |
false |
Enables automatic hooking of unhandled framework and platform exceptions (opt-in). |
initialBubbleAlignment |
Alignment |
Alignment.centerRight |
Initial viewport anchor position for the floating bubble. |
redaction |
DebugRedactionConfig |
const DebugRedactionConfig() |
Rules for tokenized sensitive key masking and regex pattern scanning. |
theme |
DebugBubbleTheme |
const DebugBubbleTheme() |
Visual appearance configuration for bubble and dashboard components. |
onExport |
FutureOr<void> Function(String)? |
null |
Callback invoked during export operations (e.g., uploading to a remote service). |
Sensitive Data Redaction (DebugRedactionConfig) #
Configures data sanitization across messages, metadata, and JSON payloads:
| Property | Type | Default Value | Description |
|---|---|---|---|
enabled |
bool |
true |
Controls active redaction. Enforced active in release mode as defense-in-depth. |
sensitiveKeys |
Set<String> |
{'password', 'token', 'auth', 'secret', ...} |
Key substrings that trigger value replacement with [REDACTED]. |
sensitiveKeyTokens |
Set<String> |
{'pwd', 'apikey', 'bearer', ...} |
Exact tokens checked against compound camelCase and snake_case keys. |
valuePatterns |
List<RegExp> |
[] |
Regex patterns executed against string values (e.g., credit card or tax identifiers). |
replacement |
String |
'[REDACTED]' |
Replacement mask injected for sanitized data. |
Theming Configuration (DebugBubbleTheme) #
| Property | Type | Default Value | Description |
|---|---|---|---|
mode |
ThemeMode |
ThemeMode.system |
Brightness mode: ThemeMode.system, ThemeMode.dark, or ThemeMode.light. |
bubbleColor |
Color? |
null |
Background color override for the floating bubble. |
bubbleIconColor |
Color? |
null |
Icon tint override for the floating bubble. |
levelColors |
Map<DebugLogLevel, Color>? |
null |
Custom color palette overrides mapped by severity level. |
Examples #
API & Network Logging #
try {
final response = await httpClient.get(Uri.parse('https://api.example.com/profile'));
if (response.statusCode == 200) {
DebugLog.success(
'User profile loaded',
tag: 'Profile',
json: jsonDecode(response.body),
);
} else {
DebugLog.warning(
'Profile request returned non-200 status',
tag: 'Profile',
metadata: {'statusCode': response.statusCode},
json: jsonDecode(response.body),
);
}
} catch (error, stackTrace) {
DebugLog.error(
'Failed to load user profile',
tag: 'Profile',
error: error,
stackTrace: stackTrace,
);
}
Unhandled Error Capture #
When captureUncaughtErrors: true is configured, errors thrown during widget build or layout phases are routed directly to the dashboard:
// Captured automatically via FlutterError.onError
throw FlutterError('RenderBox constraints violated');
Programmatic Controller Access #
The active default controller can be accessed via DebugLog.controller to inspect buffer state, manage the overlay, or export logs:
// Open or close the dashboard overlay programmatically
DebugLog.controller?.openDashboard();
DebugLog.controller?.closeDashboard();
// Query in-memory buffer statistics
final totalEntries = DebugLog.controller?.entryCount ?? 0;
final errorCount = DebugLog.controller?.errorCount ?? 0;
final evictedCount = DebugLog.controller?.droppedCount ?? 0;
// Export filtered logs on demand
final jsonReport = DebugLog.controller?.exportJson();
final textReport = DebugLog.controller?.exportText();
// Clear buffer manually
DebugLog.controller?.clear();
Production & Release Mode #
When compiled in release mode (kReleaseMode):
DebugBubbleControlleris completely inert.DebugLogcalls are dropped immediately with zero memory allocation.- No global error hooks are installed.
DebugBubblereturns onlywidget.childwithout allocating overlay or gesture hierarchies.
Author #
Developed and maintained by Satyam Gawali.
Contributions, feedback, and issue reports are always welcome!
License #
This package is distributed under the MIT License. See LICENSE for details.



