dio_debug_logger 0.4.1
dio_debug_logger: ^0.4.1 copied to clipboard
In-app network inspector for Dio: searchable request list, request and response details, stats, retry, cURL export and dev/staging/prod switching.
dio_debug_logger #
An in-app network inspector for Dio. Adds a draggable debug button to your app that opens a full log viewer: request list with search and filters, request / response / error details, statistics, retry, and cURL / Postman / JSON export.
Setup takes two lines, and both are automatically disabled in release builds. ๐ Safe by default โ see Security & privacy.
| Feature | |
|---|---|
| Draggable floating button with request/error badge | โ |
| Log list with search and status filter | โ |
| Request / Response / Error details with JSON tree view | โ |
| Statistics (success rate, slowest/fastest, by method) | โ |
| Copy as cURL / Postman / JSON / readable summary | โ |
| Retry a request | โ |
| Passwords, tokens and keys masked everywhere (UI, console, copy, export) | โ |
| Responsive (phone โ tablet, large fonts) | โ |
| Switch between backends (dev / staging / prod) at runtime | โ |
Installation #
flutter pub add dio_debug_logger
Setup (2 lines) #
import 'package:dio_debug_logger/dio_debug_logger.dart';
// 1) Record the requests of your Dio instance
final dio = Dio()..addDebugLogger();
// 2) Show the debug button
MaterialApp(
builder: DioDebugLogger.builder(),
home: const HomePage(),
);
That's it. Tap the ๐ button to open the logs.
- Both lines do nothing in release builds (
kDebugModeis the default), so you don't need to remove them before shipping. - No
navigatorKeyornavigatorObserversneeded โ the navigator is found automatically.
Already have a builder? #
Pass it in โ the debug button is placed on top of it:
MaterialApp(
builder: DioDebugLogger.builder(
builder: (context, child) => MediaQuery(
data: MediaQuery.of(context).copyWith(textScaler: TextScaler.noScaling),
child: child!,
),
),
);
Enable it in other environments #
Pass enabled to both lines, for example to show it in a staging build:
dio.addDebugLogger(enabled: isStaging);
MaterialApp(builder: DioDebugLogger.builder(enabled: isStaging));
Security & privacy #
A network logger sees everything your app sends, so it is built to be safe by default. Every point below is covered by tests.
Nothing runs in production
addDebugLogger(),DioDebugLogger.builder(),setEnvironments(), theDebugLogginginterceptor and theDebugOverlaywidget are all off in release builds unless you passenabled: trueyourself. Off means: no recording, no button, no URL rewriting โ requests pass through untouched.- The deprecated
NetworkLoggerAPI follows the same rule. - If you do enable it in a release build (e.g. an internal QA build), a warning is printed so it
can't slip into a store build unnoticed, and
DioDebugLogger.open()only works after such an explicit opt-in.
Secrets are masked everywhere
Passwords, tokens, API keys, cookies, OTP/PIN codes and card data are replaced with โขโขโขโขโขโข:
| Where | Headers | Body fields | URL query |
|---|---|---|---|
| Log UI (tap ๐ on the detail page to reveal, resets on restart) | โ | โ | โ |
| Console output | โ | โ | โ |
| Copy as cURL / Postman / JSON / summary (Hide secrets, on by default) | โ | โ | โ |
Copy all as JSON / exportAll() |
โ | โ | โ |
Field names are matched in any style โ password, access_token, refreshToken, X-Api-Key,
client_secret, pin, cvvโฆ Nested JSON, JSON strings, form-encoded bodies and FormData
are all handled. Add your own fields:
DioDebugLogger.sensitiveKeys.addAll({'national_id', 'iban', 'diagnosis'});
Nothing is stored or sent anywhere
- Logs live in memory only (last 200 requests by default) and disappear when the app closes. Nothing is written to disk except the name of the selected environment.
- The package makes no network calls of its own and has no analytics.
- The environment switcher only offers the base URLs written in your code โ there is no field to type an arbitrary address, and requests to other hosts are never changed.
- Retry resends with the same Dio that made the request, so certificate pinning and your
interceptors still apply (or set
DioDebugLogger.retryClientBuilder).
Your part
- Don't pass
enabled: trueto builds that go to app stores. - If your API uses unusual names for secret or personal fields, add them to
DioDebugLogger.sensitiveKeys.
Switching environments #
Switch the backend at runtime from the log page โ no rebuild, no flavors. List your environments when adding the logger:
final dio = Dio(BaseOptions(baseUrl: 'https://api.example.com'))
..addDebugLogger(environments: const [
DebugEnvironment('Dev', baseUrl: 'https://dev.api.example.com', color: Colors.green),
DebugEnvironment('Staging', baseUrl: 'https://staging.api.example.com', color: Colors.orange),
DebugEnvironment('Prod', baseUrl: 'https://api.example.com', color: Colors.red),
]);
Tap the environment under the Network Logs title to switch. New requests go to the selected
base URL, the button shows a badge (DEV, STAโฆ), and the choice is remembered after restarts.
Default uses the base URL configured in your code.
-
Safe in production: in release builds the logger isn't added, so nothing is rewritten.
-
Only requests whose base URL is one of the listed ones are changed โ requests to other hosts (CDNs, absolute URLs) are left alone. Your Dio's own
baseUrlshould be in the list. -
Several Dio instances (e.g. API and auth): give each its own list with the same names โ selecting
Devswitches all of them. -
Dio created lazily? Declare the environments in
main()so the switcher is there before the first request. Every Dio without its own list uses them:DioDebugLogger.setEnvironments(const [ DebugEnvironment('Dev', baseUrl: 'https://dev.api.example.com'), DebugEnvironment('Prod', baseUrl: 'https://api.example.com'), ]); -
Switching backends usually invalidates the session โ react to it:
DioDebugLogger.onEnvironmentChanged = (name) => authService.logout(); DioDebugLogger.environment; // selected name, or null for default await DioDebugLogger.setEnvironment('Dev'); // from code (null = default)
Configuration #
DioDebugLogger.builder(
enabled: kDebugMode, // default
backgroundColor: Colors.indigo,
foregroundColor: Colors.white,
icon: Icons.bug_report_rounded,
buttonSize: 56,
showBadge: true, // request / error count
initialAlignment: Alignment.centerLeft,
snapToEdge: true, // snap to the nearest edge when released
);
dio.addDebugLogger(
enabled: kDebugMode, // default
printToConsole: kDebugMode, // default
redactSensitiveHeaders: true, // mask Authorization etc. in the console
maxConsoleBodyLength: 2000,
);
// How many requests are kept in memory (default 200)
DioDebugLogger.configure(maxRequests: 500);
// Use your own Dio for the "Retry" button (certificate pinning, base options, ...)
DioDebugLogger.retryClientBuilder = () => myDio;
Opening the logs from code #
DioDebugLogger.open(context);
DioDebugLogger.close(context);
DioDebugLogger.isOpen; // bool
DioDebugLogger.isOpenNotifier; // ValueListenable<bool>
Accessing the logs directly #
final storage = DioDebugLogger.storage; // singleton ChangeNotifier
storage.count;
storage.errorCount;
storage.successCount;
storage.pendingCount;
storage.averageElapsedMs;
storage.requests; // List<DebugModel>, newest first
storage.setRecording(false); // pause recording
storage.clear();
storage.deleteById(id);
storage.exportAll(redact: true); // List<Map<String, dynamic>>
What's on the log page #
- Search by URL, method or status code
- Filter โ All / Success / Errors / Pending
- Multi-select โ long press to select, delete in bulk
- Swipe to delete a single log
- โฎ menu โ Analytics, Pause recording, Copy all as JSON, Clear all
- Details โ Request / Response / Error tabs, JSON tree โ raw text, headers, size and duration
- Copy โ cURL, Postman collection, JSON, readable summary, response body only (Hide secrets, on by default, masks passwords, tokens and keys)
- Retry โ resend the request and see the result in place
Migrating from 0.1.x #
The old API still works but is deprecated:
| Old | New |
|---|---|
dio.interceptors.add(DebugLogging()) |
dio.addDebugLogger() (the old form is still fine) |
NetworkLogger.overlayBuilder(...) |
DioDebugLogger.builder(...) |
NetworkLogger.open/close/... |
DioDebugLogger.open/close/... |
openDebugPage(context) |
DioDebugLogger.open(context) |
Note:
NetworkLogger.overlayBuilder()was enabled by default;DioDebugLogger.builder()is only enabled in debug builds unless you passenabled.
Author #
Made by Samir Aghayev, Senior Flutter Developer.
