ConsolePlus

Pub package: https://pub.dev/packages/console_plus
Repository: https://github.com/ashish8381/console_plus

A floating in-app console for Flutter β€” view, filter, search & export logs while your app runs!
console_plus lets you debug on-device with a floating overlay console that captures print() and debugPrint() in real time.


πŸ†• Version 2.0.0 & 2.0.1 Highlights

πŸš€ Major Rewrite for Stability & Zone Safety

  • 🧭 Zone-safe initialization β€” no more β€œZone mismatch” errors.
  • πŸͺ„ Unified log capture β€” print() + debugPrint() + platform errors all logged automatically.
  • 🧩 Cleaner API β€” single ConsolePlus.initApp() entry point.
  • 🎨 Redesigned console UI β€” smoother, resizable, searchable overlay.
  • πŸ§ͺ Better Flutter Test compatibility β€” works seamlessly inside test zones.

✨ Features

βœ… Floating draggable console overlay
βœ… Logs display above your app’s UI (non-blocking)
βœ… Captures print() and debugPrint()
βœ… Auto-scroll when near the bottom
βœ… Filter logs by type (INFO, WARNING, ERROR)
βœ… Keyword search for tags or text
βœ… Runtime toggle: high-performance (virtualized) vs full-text mode
βœ… Saved search queries per profile
βœ… Command palette (pause, clear, export templates, copy filtered logs)
βœ… Optional custom actions API for console extensions
βœ… Copy, clear, and export logs as JSON
βœ… Built-in floating 🐞 debug button
βœ… Captures FlutterError and PlatformDispatcher errors
βœ… Compatible with Flutter 3.16+ / Dart 3+


βš™οΈ Installation

Add to your pubspec.yaml:

dependencies:
  console_plus: ^2.0.2

Then fetch packages:

flutter pub get

Import it:

import 'package:console_plus/console_plus.dart';

πŸ’» Usage

Step 1 β€” Initialize ConsolePlus

Wrap your app inside ConsolePlus.initApp():

Future<void> main() async {
  await ConsolePlus.initApp(
    const MyApp(),
    interceptPrints: true,          // Capture print() and debugPrint()
    captureFlutterErrors: true,     // Capture Flutter framework errors
    capturePlatformErrors: true,    // Capture platform dispatcher errors
  );
}

🧠 This ensures WidgetsFlutterBinding and runApp() are initialized in the same zone β€” no more zone mismatch errors!

Step 2 β€” Show Floating Debug Button

FloatingDebugButton.show(context);

This shows a draggable 🐞 button that opens the console overlay.


Step 3 β€” Log Messages

Use:

DebugLogConsole.log("User logged in successfully");
DebugLogConsole.log("Missing field: email", type: LogType.warning);
DebugLogConsole.log("API request failed", type: LogType.error);

Or just use:

print("Something happened");
debugPrint("App started!");

Both are automatically captured by ConsolePlus.

Switch rendering mode at runtime:

DebugLogConsole.highPerformanceMode = true; // virtualized, faster
DebugLogConsole.highPerformanceMode = false; // full selectable text block

Saved queries profile + custom actions:

await DebugLogConsole.setSavedQueryProfile('qa-staging');

DebugLogConsole.registerCustomAction(
  ConsoleCustomAction(
    id: 'quick-note',
    label: 'Add Quick Note',
    icon: Icons.note_add_outlined,
    onExecute: (context, filteredLogs) async {
      DebugLogConsole.addLog('Quick note | filtered: ${filteredLogs.length}');
    },
  ),
);

Mode Selection Guide

Expected Log Volume Recommended Mode Why
< 500 logs/session Full-text Best for copy/select across one continuous block
500 - 2000 logs/session High-performance Better frame stability while preserving per-line selection
2000+ logs/session or burst logging High-performance Strongest protection against UI jank and input lag

Step 4 β€” Export Logs

Tap the ⬇️ Download icon in the console header to export as a .json file.

You can also programmatically call:

final json = await DebugLogConsole.exportLogs(asJson: true);

πŸŽ›οΈ Console UI

  • 🟒 Floating, draggable, and resizable window
  • πŸ” Search bar with keyword filtering
  • 🧩 Filter by log levels (Info / Warning / Error)
  • πŸ“‹ Copy, ⬇️ Export, πŸ—‘οΈ Clear logs
  • πŸ“œ Persistent scroll + multi-line selection
  • ⚑ Real-time updates powered by ValueNotifier

🧩 Example (Benchmark App)

import 'package:console_plus/console_plus.dart';
import 'package:flutter/material.dart';

Future<void> main() async {
  await ConsolePlus.initApp(
    const ConsolePlusExampleApp(),
    interceptPrints: true,
    captureFlutterErrors: true,
    capturePlatformErrors: true,
  );
}

class ConsolePlusExampleApp extends StatelessWidget {
  const ConsolePlusExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ConsolePlus Benchmark',
      theme: ThemeData.dark(useMaterial3: true),
      home: const BenchmarkPage(),
    );
  }
}

The example app now includes:

  • Runtime mode switch (High Performance Mode)
  • Run 1k Benchmark and Run 5k Benchmark buttons
  • Live metrics: enqueue time, first UI update latency, settle time, estimated FPS

Open example/lib/main.dart for the full benchmark implementation.

πŸ“‚ File Export

Format: .json

Example output:

[
  {
    "timestamp": "2025-11-08T12:30:01.345Z",
    "type": "info",
    "message": "App started"
  },
  {
    "timestamp": "2025-11-08T12:31:14.123Z",
    "type": "error",
    "message": "Network timeout"
  }
]

🧭 Upgrading from v1.x β†’ v2.0.1

Before:

void main() {
  ConsolePlus.init(MyApp());
  runApp(MyApp());
}

After (v2.0.0):

Future<void> main() async {
  await ConsolePlus.initApp(
    const MyApp(),
    interceptPrints: true,
    captureFlutterErrors: true,
    capturePlatformErrors: true,
  );
}

βœ… ConsolePlus.init() β†’ replaced with ConsolePlus.initApp() βœ… Initialization now must be awaited βœ… Zone-safe by default β€” fixes zone mismatch crashes βœ… No more manual WidgetsFlutterBinding.ensureInitialized() calls required

Contributing

PRs welcome. Keep debug-only behaviour intact. If you add native platform code, ensure release builds keep plugin inert unless explicitly enabled.


πŸ“œ License

MIT License Β© 2025 Ashish
See the full LICENSE file for details.


πŸ’¬ Credits

Built with ❀️ by Ashish Follow for updates and Flutter dev tips!