api_network_logger 1.1.0 copy "api_network_logger: ^1.1.0" to clipboard
api_network_logger: ^1.1.0 copied to clipboard

A production-ready, publishable Flutter package that transparently logs and stores API calls, offline events, and navigation routes.

api_network_logger #

pub package License: MIT Automated Tests

A premium, production-ready, publishable Flutter package designed to transparently capture, log, compress, and inspect your application's network traffic, offline events, and navigation route transitions into a secure on-device SQLite database.

It includes a draggable, glassmorphic visual debugging console that is fully tree-shaken and stripped from release builds (kDebugMode gated) to protect production performance and bundle sizes.


📖 Table of Contents #

  1. Key Features & Architectural Mechanics
  2. 60-Second Setup Guide
  3. Client Integration Guides
  4. Routing & Navigation Transitions Observability
  5. Pre-Storage PII Security & Redaction Engine
  6. On-Device Storage, Retention Policy, & Indexing
  7. Programmatic Database Query APIs
  8. Log Export & Remote Upload Mechanics
  9. Premium Glassmorphic Developer Console Overlay
  10. Comprehensive Edge Case & Troubleshooting Catalog
  11. License

🛠 Key Features & Architectural Mechanics #

api_network_logger was designed by senior mobile architects specifically to solve developer telemetry needs without introducing common performance regressions. Here are the core mechanics under the hood:

  • Concurrency-Safe SQLite Queue: SQLite is single-writer. In standard multi-threaded network environments (like loading a screen that triggers 5 parallel HTTP calls), rapid simultaneous inserts can lead to database locks or corrupted/dropped rows. We utilize a sequential asynchronous lock queue in Dart to serialize database transactions, protecting your app's thread.
  • Non-Destructive Stream Buffering: Streamed HTTP responses (especially in the http package) can only be read once. Our HttpApiLoggerClient safely buffers incoming bytes, extracts metadata, and re-emits a cloned stream so your application code never breaks or crashes on consumer pipes.
  • Smart Payload Compression: To preserve user storage, any request/response body exceeding 10 KB is zlib-compressed prior to storage. SQLite handles the raw byte arrays dynamically as BLOB fields, unpacking them on the fly only during inspection.
  • Binary, Form-Data, & Media Exclusion: Standard string logging on binary outputs (like image downloads or PDF views) causes UTF-8 parsing crashes and database bloat. This package scans incoming content-types. Binary streams (image/*, video/*, application/pdf, multipart/form-data) are bypassed and logged as highly compressed diagnostic summaries (e.g. [Binary Content: image/png - 2.4 MB]).

⚡ 60-Second Setup Guide #

1. Add Dependency #

Add api_network_logger to your pubspec.yaml:

dependencies:
  api_network_logger: ^1.0.0

2. Initialize (Idempotent) #

Initialize the controller once in your main thread (consecutive calls, such as during hot-reloads, are safely ignored and will never duplicate resources or timers):

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // Initialize with zero-config defaults
  await ApiLogger.instance.init();

  runApp(const MyApp());
}

3. Add the Glassmorphic Visual Console Overlay #

The visual floating overlay debugger should be wrapped in your MaterialApp's builder parameter. This is the standard, elite design pattern to ensure that the visual overlay sits above all router pages while remaining inside your Material style tree (giving it full access to directionality, localizations, navigator contexts, and custom themes):

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Tractal App',
      theme: ThemeData(useMaterial3: true, primaryColor: const Color(0xFF2CAC5C)),
      // Mount the debugger overlay seamlessly!
      builder: (context, child) => ApiLoggerOverlay(child: child!),
      // Register navigator observer to automatically log page transitions
      navigatorObservers: [ApiLoggerNavigatorObserver()],
      home: const HomeScreen(),
    );
  }
}

🔌 Client Integration Guides #

A. Dio Client (Interceptor) #

Simply append our interceptor to your shared Dio instance. Our interceptor generates a unique correlation ID and attaches it to Dio's RequestOptions.extra map, guaranteeing correct stopwatch-duration pairing even under massive concurrent request traffic:

final dioClient = Dio(
  BaseOptions(baseUrl: 'https://api.mydomain.com'),
);

// Add the transparent interceptor
dioClient.interceptors.add(DioApiLoggerInterceptor());

B. Standard http package (Wrapper) #

If your app uses the standard http package, swap out your standard client initialization for our streamed logger wrapper. It acts as a direct, drop-in replacement:

// OLD: final client = http.Client();
// NEW (just swap the constructor!):
final client = HttpApiLoggerClient();

// Use exactly like standard client! All calls are captured seamlessly:
final response = await client.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));

C. Manual Logging Fallback #

If you are using raw socket clients, custom Dart backend gateways, or third-party wrappers without standard interceptor hooks, you can programmatically ingest logs manually:

final stopwatch = Stopwatch()..start();
try {
  final response = await myCustomFetchGateway(url);
  stopwatch.stop();

  ApiLogger.instance.logApi(
    ApiLogEntry(
      id: UniqueKey().toString(),
      method: 'POST',
      url: url,
      requestHeaders: {'Content-Type': 'application/json'},
      statusCode: response.statusCode,
      responseBody: response.body,
      durationMs: stopwatch.elapsedMilliseconds,
      timestamp: DateTime.now(),
    ),
  );
} catch (e) {
  stopwatch.stop();
  // Capture failed exception entries
  ApiLogger.instance.logApi(
    ApiLogEntry(
      id: UniqueKey().toString(),
      method: 'POST',
      url: url,
      requestHeaders: {},
      error: e.toString(),
      durationMs: stopwatch.elapsedMilliseconds,
      timestamp: DateTime.now(),
    ),
  );
}

🧭 Routing & Navigation Transitions Observability #

Understanding user journeys alongside network calls is critical for troubleshooting bug logs. This package provides dynamic routing observability out of the box.

Automatic Navigator Observer #

Simply drop our custom observer into your MaterialApp to automatically intercept, decode, and log standard page transitions into your local database:

MaterialApp(
  navigatorObservers: [ApiLoggerNavigatorObserver()],
  ...
)

Custom Router Hooks (GoRouter, AutoRoute, Custom Routers) #

If you are using modern router packages that handle page transitions dynamically (such as GoRouter), you can manually publish custom navigation routes directly to our engine:

// In your custom router callback or transition builder:
ApiLogger.instance.logNavigation(
  fromRoute: '/login_screen',
  toRoute: '/dashboard',
  arguments: {
    'user_tier': 'premium',
    'session_token_id': 9982,
  },
);

🔒 Pre-Storage PII Security & Redaction Engine #

Plaintext authentication credentials, access tokens, and passwords should never be stored on user device memory due to risks in rooted/jailbroken devices.

api_network_logger implements a strict Pre-Storage Redactor. It parses your headers and recursive JSON structures, replacing matching credentials with [REDACTED] before any database serialization or disk writes occur:

Incoming API Call (Plaintext) 
      │
      ├──> [Authorization: Bearer my_secret_token_123]
      └──> {"user": "satish", "password": "super_secret_password"}
      │
┌─────▼──────────────────────────────┐
│  REDACTOR pre-storage filter engine │
└─────┬──────────────────────────────┘
      │
      ├──> [Authorization: [REDACTED]]
      └──> {"user": "satish", "password": "[REDACTED]"}
      │
      ▼
SQLite DB (Written Safely to Disk)

Configurable Redaction Keywords #

You can extend or modify the default case-insensitive redaction lists in your ApiLoggerConfig:

ApiLogger.instance.init(
  config: const ApiLoggerConfig(
    // Case-insensitive header keys
    redactedHeaders: ['Authorization', 'Cookie', 'X-Auth-Token', 'My-Custom-Token'],
    // Case-insensitive JSON keys (walks nested objects and lists recursively)
    redactedFields: ['password', 'token', 'cvv', 'card_number', 'ssn'],
  ),
);

Strict Encrypted rest Storage #

By default, the package relies on an unencrypted local SQLite file. If your application has strict compliance requirements (such as HIPPA or PCI), implement the abstract LogStorage contract using secure containers (like sqlcipher) and inject it on boot:

class EncryptedStorage implements LogStorage {
  // Implement interface and write encrypted queries using flutter_sqlcipher...
}

// Bind to runtime configuration:
await ApiLogger.instance.init(
  config: ApiLoggerConfig(
    customStorage: EncryptedStorage(),
  ),
);

📦 On-Device Storage, Retention Policy, & Indexing #

  • Default Backing Store: Handled by SQLite (sqflite package), storing log tables inside the system-secured application documents directory.
  • Indices for Speed: Highly indexed tables (idx_api_logs_timestamp, idx_api_logs_method, idx_api_logs_status) maintain sub-millisecond query performance over thousands of logs.
  • Auto-Purge Background Timers: Periodically clears expired data. Features a dual-interval purger: runs once immediately on app boot, and starts a low-impact periodic timer that executes every 12 hours.
  • Custom Retention Policies: Sane retention configurations can be tailored to match your specific developer cycles:
    • LogRetentionPreset.threeDays
    • LogRetentionPreset.sevenDays
    • LogRetentionPreset.fourteenDays
    • LogRetentionPreset.oneMonth (Default, 30 days)
    • LogRetentionPreset.threeMonths
    • Custom Duration overrides (e.g. Duration(hours: 12)).

🔍 Programmatic Database Query APIs #

You can build your own dedicated telemetry views or manually extract entries using our robust, parameterized query methods:

final logs = await ApiLogger.instance.getApiLogs(
  from: DateTime.now().subtract(const Duration(hours: 24)),
  to: DateTime.now(),
  method: 'POST',                  // Optional: Case-insensitive method filters
  statusCodes: [401, 403, 500],    // Optional: Exact response code matching
  searchQuery: 'payments',         // Optional: Full-text search (scans URLs, bodies, and exception errors)
  minDurationMs: 150,              // Optional: Filter laggy responses
  hasError: true,                  // Optional: Filter error/exceptions paths only
  limit: 50,                       // Optional: Paginate results
  offset: 0,                       // Optional: Paginate results
);

// Returns empty list instead of null/throwing if no logs are found:
if (logs.isEmpty) {
  print('No logs matched filters.');
}

📤 Log Export & Remote Upload Mechanics #

Trigger log pushes on-demand directly from your UI (such as in a "Report an Issue" or "Developer Settings" button):

try {
  final success = await ApiLogger.instance.exportLogs(
    from: DateTime.now().subtract(const Duration(days: 7)),
    to: DateTime.now(),
  );
  if (success) {
    print('Logs successfully uploaded to remote export endpoint!');
  }
} on ApiLoggerExportException catch (e) {
  print('Log Export Rejected: ${e.message} (Status: ${e.statusCode})');
  // Local logs remain entirely safe and untouched on export failures!
}

Export configurations #

Ensure the remote upload parameters are set up in your ApiLoggerConfig:

ApiLogger.instance.init(
  config: const ApiLoggerConfig(
    exportEndpoint: 'https://telemetry.mycorp.com/api/v1/ingest',
    exportHeaders: {
      'Authorization': 'Bearer corporate_developer_auth_jwt_key',
      'X-Client-Platform': 'Flutter-Android',
    },
  ),
);

🎨 Premium Glassmorphic Developer Console Overlay #

The visual floating bug reporter (ApiLoggerOverlay) is an interactive panel designed with a premium, glassmorphic dark-theme SaaS aesthetic.

Developer Experience Controls #

  • Draggable Floating Bubble: Draggable coordinates bound inside screen limits, saving state with responsive layout resizing.
  • Comprehensive Search Bar: Scans matching URL paths, status codes, and exception data instantly on key submit.
  • Quick Filters: Fast toggle chips separating GET, POST, PUT, DELETE methods, and specific response ranges (2xx, 4xx, 5xx, Errors Only).
  • Copy-to-Clipboard: Copy URLs, full headers, formatted JSON body nodes, or exception stack-traces with a single tap.
  • Remote Sync Button: Triggers JSON telemetry export on-demand directly from the dashboard header.
  • Hard Wipe: Safe dropdown panel to permanently drop database index tables on test cycles.

⚠️ Comprehensive Edge Case & Troubleshooting Catalog #

🚀 Large API Payloads (> 100 KB, > 1 MB, Multipart Files) #

  • Issue: Storing massive files (like profile image uploads) inside SQLite leads to immediate database size bloating and UI lag.
  • Mitigation: We set maxBodySize: 100KB by default. Any payload exceeding this limit is cleanly truncated with a [truncated] marker, omitting heavy byte lines.
  • Local Assets: Multipart upload maps or downloaded files do not write raw binary to disk. Instead, we scan content headers and represent them as metadata descriptors (e.g. [Binary Content: image/png - 2.4 MB]).

📦 HTML / Non-JSON responses #

  • Issue: Standard interceptors crash or fail to format when trying to parse HTML error outputs or plain-text strings.
  • Mitigation: Our recursive parsing engine handles plain text gracefully. If parsing as JSON fails, it skips formatting, wrapping the raw text cleanly inside a scrollable monospace console tile.

🚫 "No Directionality Widget Found" Crash #

  • Issue: Mounting the ApiLoggerOverlay wrapping MaterialApp directly causes Flutter to throw context failures because no Directionality or MediaQuery ancestor is available on the root element.
  • Mitigation: Always wrap the overlay in your MaterialApp.builder parameter (as demonstrated in the Setup Guide). This places the debugger context inside the Material tree with full access to themes and directions. If mounted outside, our overlay fallback automatically injects a standard Directionality(textDirection: TextDirection.ltr, child: ...) to protect the run state.

🔄 Multi-Threaded Concurrent Parallel Calls #

  • Issue: Parallel requests fired in the same millisecond overwrite stopwatch timing maps, corrupting captured latencies.
  • Mitigation: We generate an unique tracking transaction ID on onRequest and correlate it to standard response objects dynamically, completely isolating concurrent timestamps.

🧱 Android Studio Invisible Files Tree #

  • Issue: When opening a pure Flutter package folder, Android Studio's file explorer displays an empty folder structure or shows no workspace files.
  • Mitigation:
    1. We generated a fresh, fully configured api_network_logger.iml file and updated .idea/modules.xml accordingly.
    2. Change your Android Studio file explorer dropdown view (top-left of the explorer tab) from "Android" to "Project" (or "Project Files"). This will immediately reveal the full tree.

📄 License #

Distributed under the MIT License. See LICENSE for more information.


📦 More Packages by the Author #

Expand your Flutter toolkit with these high-performance, developer-friendly solutions:

Package Badges Description
page_navigation_transition pub package Seamlessly customize page route transitions with beautiful fluid curves and durations.
photo_opener_view pub package Premium gesture-driven interactive photo viewer with fluid swipe-to-dismiss and dragging.
smart_review_prompter pub package Intelligent, high-conversion in-app store review dialog prompter to skyrocket app ratings.

👨‍💻 Author #

Satish Parmar

GitHub    Portfolio

🌐 Portfolio


⭐ If you like this package, please give it a star on GitHub! ⭐

Copyright (c) 2026 Tractal Solutions Private Limited.

2
likes
160
points
151
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A production-ready, publishable Flutter package that transparently logs and stores API calls, offline events, and navigation routes.

Repository (GitHub)

License

MIT (license)

Dependencies

dio, flutter, http, meta, path, path_provider, sqflite

More

Packages that depend on api_network_logger