Why Choose api_network_logger?

The api_network_logger Flutter package gives you a ready‑made, production‑grade logger for every network call your app makes. It removes the need to write custom interceptors, file writers, or SQLite helpers just to keep a trace of API traffic. If you need quick visibility into request URLs, headers, payloads, and response status while still keeping the logger behind a clear architectural boundary, this package is a solid fit.

Installation

Add the dependency with the Flutter CLI:

Code
flutter pub add api_network_logger

After the command finishes, run flutter pub get to fetch the package.

Basic Setup

Initialize the logger before your UI starts. The typical place is at the top of main() after ensuring the Flutter bindings are ready.

Dart / Flutter
import 'package:flutter/material.dart';
import 'package:api_network_logger/api_network_logger.dart';

Future main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // The exact API may differ – verify the parameters on pub.dev.
  await ApiNetworkLogger.initialize(
    storagePath: 'api_logs',               // Directory where logs are stored
    maxFileSizeInBytes: 5 * 1024 * 1024,   // Rotate after 5 MiB
    enableOfflineQueue: true,             // Optional: store failed calls
  );

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'FlutterFever Demo',
      home: const HomePage(),
    );
  }
}

Creating a Network Service

Wrap your HTTP client in a service class so the logger stays isolated from UI code. Below is a minimal example using the popular http package.

Code
import 'package:http/http.dart' as http;
import 'package:api_network_logger/api_network_logger.dart';

class ApiService {
  final http.Client _client;
  final ApiNetworkLogger _logger = ApiNetworkLogger.instance;

  ApiService({http.Client? client}) : _client = client ?? http.Client();

  Future fetchPosts() async {
    final uri = Uri.parse('https://jsonplaceholder.typicode.com/posts');

    // Log the outgoing request
    _logger.logRequest(
      uri: uri,
      method: 'GET',
      headers: {},
    );

    final response = await _client.get(uri);

    // Log the incoming response
    _logger.logResponse(
      uri: uri,
      statusCode: response.statusCode,
      body: response.body,
    );

    return response;
  }
}

Using the Service in a Widget

Keep UI code clean by calling the service from a stateful widget or a provider.

Dart / Flutter
import 'package:flutter/material.dart';
import 'api_service.dart';

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final ApiService _api = ApiService();
  String _output = '';

  Future _loadPosts() async {
    final response = await _api.fetchPosts();
    setState(() {
      _output = response.body;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Api Network Logger Demo')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            ElevatedButton(
              onPressed: _loadPosts,
              child: const Text('Fetch Posts'),
            ),
            const SizedBox(height: 20),
            Expanded(
              child: SingleChildScrollView(
                child: Text(_output),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Advanced Usage

The package also supports logging navigation routes and offline event queues. While the exact APIs may evolve, the general pattern is:

  • Call logRouteChange(String routeName) from your NavigatorObserver.
  • Enable the offline queue during initialization to automatically store failed requests and replay them when connectivity returns.

Tip: Keep the logger behind an abstraction (e.g., ILogger) so you can swap it out or mock it in unit tests without pulling the package into your domain layer.

Common Pitfalls & How to Avoid Them

  • Missing initialization: Forgetting to call ApiNetworkLogger.initialize will cause runtime null‑pointer errors. Always initialize in main() before
    Code
    runApp()
    .
  • Logging sensitive data: By default the logger records full request bodies. Filter or mask authentication tokens before calling logRequest if you need to comply with privacy regulations.
  • Unbounded file growth: Without a maxFileSizeInBytes or rotation strategy, log files can grow indefinitely on the device. Configure a sensible limit and consider a daily rotation policy.
  • Version incompatibility: The package may change its API across releases. Pin a version in pubspec.yaml and review the changelog before upgrading.

Best Practices for Production Apps

  • Wrap all logger calls in a dedicated service class.
  • Provide a compile‑time flag (e.g., bool kDebugMode = !kReleaseMode;) to disable verbose logging in release builds.
  • Store logs in a location that respects platform guidelines (e.g., getApplicationDocumentsDirectory() on iOS/Android).
  • Expose a simple UI for developers to view or export logs during QA.

When to Consider an Alternative

If your app already uses a full‑featured HTTP client like dio with interceptors, you might prefer integrating logging directly into that stack. The api_network_logger shines when you need a lightweight, package‑only solution without pulling in a larger dependency graph.

Frequently Asked Questions

Do I need to add any platform-specific permissions to use api_network_logger?

The package writes logs to the app's internal storage, which does not require extra permissions on iOS or Android. If you configure the logger to write to external storage on Android, you will need the appropriate storage permission.

Can api_network_logger be used with Dio or other HTTP clients?

Yes. The package provides generic <code>logRequest</code> and <code>logResponse</code> methods that you can call from any HTTP client, including Dio interceptors. Just make sure to forward the relevant data (URL, method, headers, body, status code) to the logger.

How do I prevent sensitive data like auth tokens from being logged?

Filter or mask sensitive fields before calling <code>logRequest</code>. For example, create a helper that removes the <code>Authorization</code> header or replaces password fields with asterisks, then pass the sanitized map to the logger.

Is there a way to export logs for debugging on a remote server?

The package stores logs as files on the device. You can read those files using standard Dart I/O APIs and upload them via your own endpoint. Check the package README for the exact file location and format.

Will the logger impact app performance?

Logging introduces minimal overhead because it writes asynchronously to disk. However, avoid logging large binary payloads in production and configure a reasonable <code>maxFileSizeInBytes</code> to keep I/O bounded.