dio_smart_logger 📡

A production-focused logging interceptor for Dio with structured output, sensitive data masking, cURL generation, and detailed error diagnostics.

pub package License: MIT

✨ Features

  • Structured Output: Clean, easy-to-read request, response, and error logs.
  • Configurable Levels: Fine-grained control with none, error, info, debug, and verbose levels.
  • Security First: Built-in sensitive data masking for headers, query params, and request/response bodies.
  • cURL Generation: Ready-to-use cURL commands for easy request reproduction.
  • Performance Metrics: Track request duration, payload size, and transfer rate.
  • Advanced Error Diagnostics: Detailed root-cause analysis mapped by DioExceptionType.
  • Flexibility: Optional request filtering and custom printer callbacks.
  • Ready-made Presets: DioLoggerConfig.development(), .production(), and .errorsOnly().
  • Per-request Opt-out: Skip logging for a single request via a request extra flag.
  • Protocol & Rate-limit Insight: Logs the negotiated HTTP version and surfaces rate-limit headers.

📦 Installation

Add the dependency to your pubspec.yaml:

dependencies:
  dio_smart_logger: ^0.3.0 # Or the latest version

Then run:

dart pub get

Or, using Flutter:

flutter pub add dio_smart_logger

🚀 Quick Start

Attach the interceptor to your Dio instance:

import 'package:dio/dio.dart';
import 'package:dio_smart_logger/dio_smart_logger.dart';

final dio = Dio();

dio.interceptors.add(
  DioLoggerInterceptor(
    config: const DioLoggerConfig(
      enabled: true,
      level: DioLogLevel.debug,
      showCurl: true,
      maskSensitiveData: true,
    ),
  ),
);

Presets

Skip the boilerplate with a ready-made configuration:

// Verbose logs, cURL, colors - ideal for local development.
dio.interceptors.add(DioLoggerInterceptor(config: DioLoggerConfig.development()));

// Errors only, no bodies or cURL, no colors - a safe default for release builds.
dio.interceptors.add(DioLoggerInterceptor(config: DioLoggerConfig.production()));

// Only failed requests, but with full forensic detail (snapshots, cURL).
dio.interceptors.add(DioLoggerInterceptor(config: DioLoggerConfig.errorsOnly()));

Tip: add the logger as the last request interceptor (so it is the first to see the response) for the most representative Duration measurement.

🛠️ Advanced Configuration

You can tailor the logger to your specific needs. Here's a comprehensive setup:

const loggerConfig = DioLoggerConfig(
  enabled: true,
  level: DioLogLevel.verbose, // Log everything
  showCurl: true,
  showPerformanceMetrics: true,
  logErrorStackTrace: true,
  maxBodyBytes: 64 * 1024, // Truncate bodies larger than 64KB
  requestFilter: _logOnlyApiHost, // Filter which requests to log
);

bool _logOnlyApiHost(RequestOptions options) {
  // Only log requests going to 'api.example.com'
  return options.uri.host == 'api.example.com';
}

dio.interceptors.add(DioLoggerInterceptor(config: loggerConfig));

Custom Printer

If you want to route logs to a specific destination (like Crashlytics, a file, or a custom logging system) instead of the console, use the printer callback:

final logs = <String>[];

final interceptor = DioLoggerInterceptor(
  config: DioLoggerConfig(
    printer: (String message) {
      logs.add(message);
      // Send to Crashlytics, Datadog, etc.
    },
    useColors: false, // Usually you don't want ANSI colors in external loggers
  ),
);

Skipping a Single Request

To suppress logging for one specific request (e.g. a noisy health check or a sensitive endpoint), set the opt-out flag in its extra:

dio.get(
  '/health',
  options: Options(extra: {DioLoggerInterceptor.disableLoggingKey: true}),
);

🔒 Security Notes

  • Auto-Masking: By default, common sensitive keys (like passwords, tokens, API keys) are masked with ***MASKED***.
  • Value-based Masking: Sensitive-looking values (e.g. Bearer tokens and JWTs) are masked even when they appear under a non-obvious key.
  • Custom Secrets: You can extend the list of masked keys for your project:
    DioLoggerConfig(
      sensitiveKeys: ['my_custom_secret', 'social_security_number'],
    )
    
  • Header Blacklist: Completely suppress specific headers from being logged using the headerBlacklist parameter.

💡 Example

Check out the example/main.dart file for a runnable setup with a mock adapter.

Run the example from the terminal:

dart run example/main.dart

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

Libraries

dio_smart_logger