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.
Libraries
- debug_bubble
- A reusable Flutter debugging toolkit with an in-app floating log viewer and error dashboard.



