http_monitor 0.0.8 copy "http_monitor: ^0.0.8" to clipboard
http_monitor: ^0.0.8 copied to clipboard

A comprehensive HTTP tracking and debugging solution for Flutter. Monitor, store, and analyze all HTTP requests and responses with SQLite storage and beautiful UI.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:http_monitor/http_monitor.dart';
import 'package:dio/dio.dart';
import 'package:http/http.dart' as http;

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

  await HttpMonitor.init(
    config: const HttpMonitorConfig(
      enabled: true,
      maxLogCount: 500,
      autoCleanupDuration: Duration(days: 3),
      maxResponseBodySize: 1024 * 512,
      enableInReleaseMode: false,
    ),
  );

  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'HTTP Monitor Example',
      theme: ThemeData(useMaterial3: true, colorSchemeSeed: Colors.blue),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

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

class _HomePageState extends State<HomePage> {
  late Dio _dio;
  late http.Client _httpClient;
  bool _isLoading = false;
  bool _isConcurrentLoading = false;

  @override
  void initState() {
    super.initState();
    _initializeClients();
  }

  void _initializeClients() {
    _dio = Dio();
    _dio.interceptors.add(
      HttpMonitorDioInterceptor(logger: HttpMonitor.instance.logger),
    );

    _httpClient = HttpMonitorClient(
      client: http.Client(),
      logger: HttpMonitor.instance.logger,
    );
  }

  @override
  void dispose() {
    _httpClient.close();
    super.dispose();
  }

  void _openMonitor() {
    Navigator.of(
      context,
    ).push(MaterialPageRoute(builder: (_) => const CombinedMonitorWidget()));
  }

  void _openHttpMonitor() {
    Navigator.of(
      context,
    ).push(MaterialPageRoute(builder: (_) => const HttpMonitorWidget()));
  }

  void _openAppLogMonitor() {
    Navigator.of(
      context,
    ).push(MaterialPageRoute(builder: (_) => const AppLogMonitorWidget()));
  }

  Future<void> _makeGetRequest() async {
    setState(() => _isLoading = true);
    
    // Log app event
    AppLogger.instance.log(
      'Starting GET request to fetch post',
      name: 'HomePage',
      stackTrace: StackTrace.current,
    );
    
    try {
      await _dio.get('https://jsonplaceholder.typicode.com/posts/1');
      
      AppLogger.instance.log(
        'GET request completed successfully',
        name: 'HomePage',
      );
      
      _showSnack('GET request completed');
    } catch (e) {
      AppLogger.instance.log(
        'GET request failed: $e',
        name: 'HomePage',
        stackTrace: StackTrace.current,
      );
      _showSnack('Error: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }

  Future<void> _makeConcurrentRequests() async {
    setState(() => _isConcurrentLoading = true);
    
    AppLogger.instance.log(
      'Starting concurrent requests test (8 requests)',
      name: 'ConcurrencyTest',
    );
    
    try {
      final stopwatch = Stopwatch()..start();

      // Test concurrent requests with Future.wait
      await Future.wait([
        _dio.get('https://jsonplaceholder.typicode.com/posts/1'),
        _dio.get('https://jsonplaceholder.typicode.com/posts/2'),
        _dio.get('https://jsonplaceholder.typicode.com/posts/3'),
        _dio.get('https://jsonplaceholder.typicode.com/posts/4'),
        _dio.get('https://jsonplaceholder.typicode.com/posts/5'),
        _dio.post('https://jsonplaceholder.typicode.com/posts', data: {
          'title': 'Test Post',
          'body': 'Test body',
          'userId': 1,
        }),
        _httpClient
            .get(Uri.parse('https://jsonplaceholder.typicode.com/users/1')),
        _httpClient
            .get(Uri.parse('https://jsonplaceholder.typicode.com/users/2')),
      ]);

      stopwatch.stop();

      AppLogger.instance.log(
        'Concurrent requests completed in ${stopwatch.elapsedMilliseconds}ms',
        name: 'ConcurrencyTest',
      );

      _showSnack(
          'Concurrent requests completed in ${stopwatch.elapsedMilliseconds}ms');
    } catch (e) {
      AppLogger.instance.log(
        'Concurrent requests failed: $e',
        name: 'ConcurrencyTest',
        stackTrace: StackTrace.current,
      );
      _showSnack('Error in concurrent requests: $e');
    } finally {
      setState(() => _isConcurrentLoading = false);
    }
  }

  Future<void> _makeHighConcurrencyTest() async {
    setState(() => _isConcurrentLoading = true);
    
    AppLogger.instance.log(
      'Starting high concurrency test (50 requests)',
      name: 'HighConcurrencyTest',
    );
    
    try {
      final stopwatch = Stopwatch()..start();

      // High concurrency test with 50 requests
      final futures = <Future>[];

      for (int i = 1; i <= 50; i++) {
        futures.add(_dio.get('https://jsonplaceholder.typicode.com/posts/$i'));
      }

      await Future.wait(futures);

      stopwatch.stop();

      AppLogger.instance.log(
        '50 concurrent requests completed in ${stopwatch.elapsedMilliseconds}ms',
        name: 'HighConcurrencyTest',
      );

      _showSnack(
          '50 concurrent requests completed in ${stopwatch.elapsedMilliseconds}ms');
    } catch (e) {
      AppLogger.instance.log(
        'High concurrency test failed: $e',
        name: 'HighConcurrencyTest',
        stackTrace: StackTrace.current,
      );
      _showSnack('Error in high concurrency test: $e');
    } finally {
      setState(() => _isConcurrentLoading = false);
    }
  }

  void _testAppLogger() {
    // Test various app log scenarios
    AppLogger.instance.log(
      'This is a simple log message',
      name: 'TestLogger',
    );
    
    AppLogger.instance.log(
      'Checking native intro ad availability: placement enabled = true',
      name: 'OnboardingAdsMixin',
      stackTrace: StackTrace.current,
    );
    
    AppLogger.instance.log(
      'User authentication state changed: logged_in',
      name: 'AuthService',
    );
    
    AppLogger.instance.logWithTrace(
      'This log includes automatic stack trace',
      name: 'AutoTraceTest',
    );
    
    // Log without name
    AppLogger.instance.log('Log without name');
    
    // Log with only stack trace
    AppLogger.instance.log(
      null,
      stackTrace: StackTrace.current,
    );
    
    _showSnack('Added 6 test app logs');
  }

  Future<void> _showQueueStatus() async {
    final queueLength = HttpMonitor.instance.logger.queueLength;
    final pendingCount = await HttpMonitor.instance.logger.pendingRequestCount;
    final appLogCount = await AppLogger.instance.getLogCount();

    _showSnack('Queue: $queueLength, Pending: $pendingCount, App Logs: $appLogCount');
  }

  void _showSnack(String msg) {
    if (mounted) {
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('HTTP Monitor Example'),
        actions: [
          IconButton(
            onPressed: _showQueueStatus,
            icon: const Icon(Icons.info_outline),
            tooltip: 'Show Queue Status',
          ),
          PopupMenuButton<String>(
            onSelected: (value) {
              switch (value) {
                case 'combined':
                  _openMonitor();
                  break;
                case 'http':
                  _openHttpMonitor();
                  break;
                case 'app':
                  _openAppLogMonitor();
                  break;
              }
            },
            itemBuilder: (context) => [
              const PopupMenuItem(
                value: 'combined',
                child: ListTile(
                  leading: Icon(Icons.dashboard),
                  title: Text('Combined Monitor'),
                  contentPadding: EdgeInsets.zero,
                ),
              ),
              const PopupMenuItem(
                value: 'http',
                child: ListTile(
                  leading: Icon(Icons.http),
                  title: Text('HTTP Monitor'),
                  contentPadding: EdgeInsets.zero,
                ),
              ),
              const PopupMenuItem(
                value: 'app',
                child: ListTile(
                  leading: Icon(Icons.article),
                  title: Text('App Log Monitor'),
                  contentPadding: EdgeInsets.zero,
                ),
              ),
            ],
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Center(
          child: SingleChildScrollView(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                // HTTP Requests Section
                const Text(
                  'HTTP Requests',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                ),
                const SizedBox(height: 12),
                
                // Single request button
                ElevatedButton.icon(
                  onPressed: _isLoading ? null : _makeGetRequest,
                  icon: _isLoading
                      ? const SizedBox(
                          width: 16,
                          height: 16,
                          child: CircularProgressIndicator(strokeWidth: 2),
                        )
                      : const Icon(Icons.download),
                  label:
                      Text(_isLoading ? 'Loading...' : 'Make GET Request (Dio)'),
                ),

                const SizedBox(height: 12),

                // Concurrent requests button
                ElevatedButton.icon(
                  onPressed:
                      _isConcurrentLoading ? null : _makeConcurrentRequests,
                  icon: _isConcurrentLoading
                      ? const SizedBox(
                          width: 16,
                          height: 16,
                          child: CircularProgressIndicator(strokeWidth: 2),
                        )
                      : const Icon(Icons.sync),
                  label: Text(_isConcurrentLoading
                      ? 'Loading...'
                      : 'Test Concurrent Requests (8 requests)'),
                  style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.green,
                    foregroundColor: Colors.white,
                  ),
                ),

                const SizedBox(height: 12),

                // High concurrency test button
                ElevatedButton.icon(
                  onPressed:
                      _isConcurrentLoading ? null : _makeHighConcurrencyTest,
                  icon: _isConcurrentLoading
                      ? const SizedBox(
                          width: 16,
                          height: 16,
                          child: CircularProgressIndicator(strokeWidth: 2),
                        )
                      : const Icon(Icons.flash_on),
                  label: Text(_isConcurrentLoading
                      ? 'Loading...'
                      : 'High Concurrency Test (50 requests)'),
                  style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.orange,
                    foregroundColor: Colors.white,
                  ),
                ),

                const SizedBox(height: 32),
                
                // App Logger Section
                const Text(
                  'App Logger',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                ),
                const SizedBox(height: 12),
                
                ElevatedButton.icon(
                  onPressed: _testAppLogger,
                  icon: const Icon(Icons.article),
                  label: const Text('Add Test App Logs'),
                  style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.purple,
                    foregroundColor: Colors.white,
                  ),
                ),

                const SizedBox(height: 32),

                const Text(
                  'Test HTTP monitoring and App logging\nwith HTTP Monitor',
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    fontSize: 16,
                    color: Colors.grey,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
      floatingActionButton: FloatingMonitorButton(
        onPressed: _openMonitor,
        childBuilder: (size) => Container(
          width: size,
          height: size,
          padding: const EdgeInsets.all(8),
          decoration: BoxDecoration(
            color: Colors.amber,
            shape: BoxShape.circle,
            boxShadow: [
              BoxShadow(
                color: Colors.black.withOpacity(0.2),
                blurRadius: 6,
                offset: const Offset(2, 3),
              ),
            ],
          ),
          child: const Icon(Icons.monitor, color: Colors.white),
        ),
      ),
    );
  }
}
3
likes
150
points
262
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

A comprehensive HTTP tracking and debugging solution for Flutter. Monitor, store, and analyze all HTTP requests and responses with SQLite storage and beautiful UI.

Repository (GitHub)
View/report issues

Topics

#http #monitoring #debugging #network #logging

License

MIT (license)

Dependencies

dio, flutter, http, mutex, path, sqflite

More

Packages that depend on http_monitor