flutter_debug_tracker: in-app debug tool for Flutter (Android & iOS)

pub package platform license: MIT GitHub stars

flutter_debug_tracker: in-app debug overlay for Flutter with FPS monitor, network inspector and Firebase Analytics viewer

flutter_debug_tracker is an in-app debugger for Flutter. A floating debug bubble sits over your app and opens a full debug panel, on the phone, without DevTools or a cable. It combines a performance monitor (FPS, jank, frame time, memory), a network inspector for HTTP requests, a logger with crash capture, a Firebase Analytics event viewer, route history, device info, a file browser and UI debugging tools.

It is inspired by DebugSwift for iOS and works on Android and iOS. Pure Dart: no native code and no third-party dependencies. It is off by default in release builds.

Screenshots

Debug bubble + HUD Performance monitor Network inspector
Floating Flutter debug bubble with live FPS and performance HUD Flutter FPS, jank, frame time and memory monitor Flutter network inspector listing HTTP requests
Request details Firebase Analytics events Logs and crashes
HTTP response headers and JSON body in the Flutter network inspector Firebase Analytics logEvent calls captured in a Flutter app Flutter in-app console with print, debugPrint and uncaught errors

Flutter UI debugging tools: grid, touches, slow animations, layout bounds
UI tools

Features

Performance monitor: FPS, jank and memory

  • Live FPS in the bubble, color-coded against the display refresh rate.
  • UI (build) and raster time per frame, a frame-time chart with the frame budget, the jank count and rate, and the worst frame.
  • Memory (RSS) and peak memory with a 2-minute history chart.
  • A compact on-screen performance HUD, toggled by long-pressing the bubble.
  • Custom traces that time your own work, such as API calls, database loads or screen builds.

Network inspector: HTTP request logger

  • Captures every dart:io HttpClient request. This covers package:http and Dio's default adapter, with no interceptor to add.
  • Shows the method, URL, status, duration and size, request and response headers, pretty-printed JSON bodies, and errors.
  • Search, an errors-only filter, and copy as cURL.

Logs and crash reporting

  • Captures print, debugPrint, DebugTracker.log, FlutterError and uncaught async errors, with stack traces.
  • Filter by level and search. The bubble shows an error badge.

Firebase Analytics event viewer

  • Every FirebaseAnalytics.instance.logEvent (and logScreenView, logPurchase, ...), plus setUserId, setUserProperty, consent and default parameters, captured automatically.
  • Events from other analytics SDKs (Mixpanel, Amplitude, your own backend) via DebugTracker.logAnalyticsEvent.

More tools

  • Routes: the current navigator stack and push/pop history.
  • App and device info: OS version, locale, CPU cores, build mode, screen size, pixel ratio, refresh rate, safe area, plus your own fields (flavor, user id, ...).
  • File browser: read-only view of the app sandbox (Documents, Library and tmp on iOS; files, cache, shared_prefs and databases on Android).
  • UI tools: Flutter's performance overlay, an 8 pt grid, touch indicators, slow animations, layout bounds and repaint rainbow.

Installation

flutter pub add flutter_debug_tracker

Requires Flutter 3.38 or newer.

Quick start

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

void main() {
  // Starts every tracker and captures print() inside the zone.
  // Do not call WidgetsFlutterBinding.ensureInitialized() before this;
  // call it inside the callback if you need it.
  DebugTracker.runZoned(() => runApp(const MyApp()));
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorObservers: [DebugTracker.observer],
      builder: DebugTracker.builder(),
      home: const HomePage(),
    );
  }
}

Run the app and tap the bubble.

Gesture Action
Tap the bubble Open the debug panel
Long-press the bubble Toggle the performance HUD
Drag the bubble Move it; it snaps to the nearest edge
System back or back swipe Close a panel page, then the panel

Already using MaterialApp.builder? Pass it through:

builder: DebugTracker.builder((context, child) => MyWrapper(child: child!)),

CupertinoApp and WidgetsApp work the same way.

Logs and custom traces

DebugTracker.log('User signed in', tag: 'auth');
DebugTracker.log('Token expires soon', level: LogLevel.warning);

final feed = await DebugTracker.trace('load feed', () => api.loadFeed());

Programmatic control

DebugTracker.open();                               // open the panel
DebugTracker.close();                              // close it
DebugTracker.instance.bubbleVisible.value = false; // hide the bubble
DebugTracker.instance.hudVisible.value = true;     // show the HUD
DebugTracker.stop();                               // remove every hook

Firebase Analytics debugging

You don't need DebugView or adb shell setprop debug.firebase.analytics.app. Start the app with DebugTracker.runZoned and keep calling Firebase as usual:

void main() {
  DebugTracker.runZoned(() async {
    WidgetsFlutterBinding.ensureInitialized(); // fine inside runZoned
    await Firebase.initializeApp();
    runApp(const MyApp());
  });
}

// Anywhere in the app: shows up in the Analytics tab right away.
await FirebaseAnalytics.instance.logEvent(
  name: 'add_to_cart',
  parameters: {'item_id': 'sku-42', 'price': 19.99},
);

How it works: the tracker installs a DebugTrackerBinding whose platform messenger reads the messages firebase_analytics sends to the native Firebase SDK. You therefore see exactly what Firebase receives, and this package does not depend on firebase_analytics.

For other providers:

DebugTracker.logAnalyticsEvent(
  'checkout_started',
  provider: 'mixpanel',
  parameters: {'cart_value': 42.5},
);

Configuration

DebugTracker.runZoned(
  () => runApp(const MyApp()),
  config: DebugTrackerConfig(
    enabled: !kReleaseMode,          // default: off in release builds
    trackPerformance: true,
    trackNetwork: true,
    trackLogs: true,
    trackErrors: true,
    trackAnalytics: true,
    showPerformanceHud: false,
    maxNetworkEntries: 200,
    maxLogEntries: 1000,
    maxAnalyticsEvents: 500,
    maxBodyBytes: 64 * 1024,
    networkIgnore: (uri) => uri.host.contains('crashlytics'),
    customInfo: {'Flavor': 'staging', 'User': '42'},
  ),
);

To ship the tracker in an internal QA build, pass enabled: true behind your own flag.

Performance overhead

A debug tool should not slow down the app it measures:

  • Frame data comes from SchedulerBinding.addTimingsCallback, which the engine already batches. No per-frame callback or ticker is added.
  • Metrics and memory are sampled once per second.
  • Captured data lives in fixed-size ring buffers, and request/response bodies are capped, so memory use does not grow with uptime. Binary bodies (images, video, fonts) are never stored.
  • List updates are coalesced, and panel widgets are only built while the panel is open.
  • The bubble only repaints when the shown FPS changes, so an idle app stays idle.
  • With enabled: false (the release default), no hook is installed.

FPS counts frames Flutter actually rendered in the last second. Flutter only renders when something changes, so an idle screen shows 0 FPS. For real numbers, run in profile mode (flutter run --profile).

FAQ

How do I inspect network requests in a Flutter app on a real device? Add DebugTracker.builder() and start with DebugTracker.runZoned. Every HttpClient, http and Dio request then appears in the Network tab with headers, body and timing. You don't need a proxy or a certificate.

How can I see Firebase Analytics events while developing? Open the Analytics tab. Each logEvent, user property and user id call appears immediately with its parameters. There is no DebugView delay.

How do I measure FPS and jank in Flutter? The bubble shows live FPS. The Performance tab shows UI and raster time per frame, the jank rate and memory. Long-press the bubble for an always-on HUD.

Does it affect my release build? No. It is disabled in release mode by default, and the overlay then renders only your app.

Does it work with Dio, GetX, Riverpod or BLoC? Yes. Network capture works below Dio's default adapter, and the overlay is a plain widget, so it works with any state management.

Limitations

  • Network capture covers dart:io HttpClient. Clients that bypass it (cupertino_http, cronet_http, native SDKs, WebViews) are not captured. If another library sets HttpOverrides.global after the tracker starts, wrap its clients with DebugTracker.instance.network.wrap(client).
  • print and Firebase Analytics are captured automatically only when the app starts with DebugTracker.runZoned.
  • Analytics events logged by native code (not through Dart) are not captured.
  • "Hide bubble" in the Tools tab hides it until you set DebugTracker.instance.bubbleVisible.value = true or restart the app.
  • Supported platforms: Android and iOS.

Example

See example/ for a demo app that generates network traffic, logs, errors, jank, traces and analytics events.

License

MIT. See LICENSE.

Libraries

flutter_debug_tracker
In-app debug overlay for Flutter apps on Android and iOS.