voo_logging 0.0.5 copy "voo_logging: ^0.0.5" to clipboard
voo_logging: ^0.0.5 copied to clipboard

A comprehensive logging package for Flutter and Dart applications with DevTools integration.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:voo_logging/voo_logging.dart';

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

  // Initialize VooLogger
  await VooLogger.initialize(appName: 'Voo Logging Example', appVersion: '1.0.0', userId: 'user123');

  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) => MaterialApp(
    title: 'Voo Logging Example',
    theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true),
    home: const LoggingExamplePage(),
  );
}

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

  @override
  State<LoggingExamplePage> createState() => _LoggingExamplePageState();
}

class _LoggingExamplePageState extends State<LoggingExamplePage> {
  final _messageController = TextEditingController();
  String _selectedLevel = 'info';
  String _selectedCategory = 'General';

  final List<String> _logLevels = ['verbose', 'debug', 'info', 'warning', 'error', 'fatal'];
  final List<String> _categories = ['General', 'Network', 'Database', 'UI', 'Analytics'];

  @override
  void dispose() {
    _messageController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) => Scaffold(
    appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: const Text('Voo Logging Example')),
    body: SingleChildScrollView(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          _buildCustomLogSection(),
          const SizedBox(height: 24),
          _buildQuickActionsSection(),
          const SizedBox(height: 24),
          _buildScenarioSection(),
          const SizedBox(height: 24),
          _buildLogManagementSection(),
        ],
      ),
    ),
  );

  Widget _buildCustomLogSection() => Card(
    child: Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('Custom Log Entry', style: Theme.of(context).textTheme.headlineSmall),
          const SizedBox(height: 16),
          TextField(
            controller: _messageController,
            decoration: const InputDecoration(labelText: 'Log Message', border: OutlineInputBorder(), hintText: 'Enter your log message'),
            maxLines: 3,
          ),
          const SizedBox(height: 16),
          Row(
            children: [
              Expanded(
                child: DropdownButtonFormField<String>(
                  value: _selectedLevel,
                  decoration: const InputDecoration(labelText: 'Log Level', border: OutlineInputBorder()),
                  items: _logLevels.map((level) => DropdownMenuItem(value: level, child: Text(level.toUpperCase()))).toList(),
                  onChanged: (value) {
                    setState(() {
                      _selectedLevel = value!;
                    });
                  },
                ),
              ),
              const SizedBox(width: 16),
              Expanded(
                child: DropdownButtonFormField<String>(
                  value: _selectedCategory,
                  decoration: const InputDecoration(labelText: 'Category', border: OutlineInputBorder()),
                  items: _categories.map((category) => DropdownMenuItem(value: category, child: Text(category))).toList(),
                  onChanged: (value) {
                    setState(() {
                      _selectedCategory = value!;
                    });
                  },
                ),
              ),
            ],
          ),
          const SizedBox(height: 16),
          SizedBox(
            width: double.infinity,
            child: ElevatedButton.icon(onPressed: _logCustomMessage, icon: const Icon(Icons.send), label: const Text('Send Log')),
          ),
        ],
      ),
    ),
  );

  Widget _buildQuickActionsSection() => Card(
    child: Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('Quick Log Actions', style: Theme.of(context).textTheme.headlineSmall),
          const SizedBox(height: 16),
          Wrap(
            spacing: 8,
            runSpacing: 8,
            children: [
              ElevatedButton(
                onPressed: () => _quickLog(LogLevel.verbose),
                style: ElevatedButton.styleFrom(backgroundColor: Colors.grey),
                child: const Text('Verbose'),
              ),
              ElevatedButton(
                onPressed: () => _quickLog(LogLevel.debug),
                style: ElevatedButton.styleFrom(backgroundColor: Colors.blue),
                child: const Text('Debug'),
              ),
              ElevatedButton(
                onPressed: () => _quickLog(LogLevel.info),
                style: ElevatedButton.styleFrom(backgroundColor: Colors.green),
                child: const Text('Info'),
              ),
              ElevatedButton(
                onPressed: () => _quickLog(LogLevel.warning),
                style: ElevatedButton.styleFrom(backgroundColor: Colors.orange),
                child: const Text('Warning'),
              ),
              ElevatedButton(
                onPressed: () => _quickLog(LogLevel.error),
                style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
                child: const Text('Error'),
              ),
              ElevatedButton(
                onPressed: () => _quickLog(LogLevel.fatal),
                style: ElevatedButton.styleFrom(backgroundColor: Colors.purple),
                child: const Text('Fatal'),
              ),
            ],
          ),
        ],
      ),
    ),
  );

  Widget _buildScenarioSection() => Card(
    child: Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('Common Scenarios', style: Theme.of(context).textTheme.headlineSmall),
          const SizedBox(height: 16),
          ListTile(leading: const Icon(Icons.network_wifi), title: const Text('Simulate Network Request'), onTap: _simulateNetworkRequest),
          ListTile(leading: const Icon(Icons.person), title: const Text('Log User Action'), onTap: _logUserAction),
          ListTile(leading: const Icon(Icons.error_outline), title: const Text('Simulate Error'), onTap: _simulateError),
          ListTile(leading: const Icon(Icons.speed), title: const Text('Log Performance Metric'), onTap: _logPerformance),
          ListTile(leading: const Icon(Icons.bug_report), title: const Text('Generate Multiple Logs'), onTap: _generateMultipleLogs),
        ],
      ),
    ),
  );

  Widget _buildLogManagementSection() => Card(
    child: Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('Log Management', style: Theme.of(context).textTheme.headlineSmall),
          const SizedBox(height: 16),
          Row(
            children: [
              Expanded(
                child: ElevatedButton.icon(onPressed: _viewStatistics, icon: const Icon(Icons.bar_chart), label: const Text('View Statistics')),
              ),
              const SizedBox(width: 8),
              Expanded(
                child: ElevatedButton.icon(onPressed: _exportLogs, icon: const Icon(Icons.download), label: const Text('Export Logs')),
              ),
            ],
          ),
          const SizedBox(height: 8),
          Row(
            children: [
              Expanded(
                child: ElevatedButton.icon(
                  onPressed: _clearLogs,
                  icon: const Icon(Icons.clear),
                  label: const Text('Clear Logs'),
                  style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
                ),
              ),
              const SizedBox(width: 8),
              Expanded(
                child: ElevatedButton.icon(onPressed: _changeUser, icon: const Icon(Icons.person_outline), label: const Text('Change User')),
              ),
            ],
          ),
        ],
      ),
    ),
  );

  void _logCustomMessage() {
    final message = _messageController.text.trim();
    if (message.isEmpty) {
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Please enter a message')));
      return;
    }

    final level = LogLevel.values.firstWhere((l) => l.name == _selectedLevel);

    VooLogger.log(
      message,
      level: level,
      category: _selectedCategory,
      tag: 'CustomLog',
      metadata: {'source': 'manual_input', 'timestamp': DateTime.now().toIso8601String()},
    );

    _messageController.clear();
    _showSnackBar('Log sent: $message');
  }

  void _quickLog(LogLevel level) {
    final messages = {
      LogLevel.verbose: 'This is a verbose message with detailed debugging info',
      LogLevel.debug: 'Debug: Component initialized successfully',
      LogLevel.info: 'User performed an action',
      LogLevel.warning: 'Warning: Approaching memory limit',
      LogLevel.error: 'Error: Failed to load resource',
      LogLevel.fatal: 'Fatal: Critical system failure',
    };

    VooLogger.log(messages[level]!, level: level, category: 'QuickAction', metadata: {'timestamp': DateTime.now().toIso8601String(), 'example': true});

    _showSnackBar('${level.name.toUpperCase()} log sent');
  }

  Future<void> _simulateNetworkRequest() async {
    // Log the request
    await VooLogger.networkRequest(
      'GET',
      'https://api.example.com/users',
      headers: {'Authorization': 'Bearer token123', 'Content-Type': 'application/json'},
      metadata: {'userId': 'user123', 'requestId': DateTime.now().millisecondsSinceEpoch.toString()},
    );

    // Log the response
    await VooLogger.networkResponse(
      200,
      'https://api.example.com/users',
      const Duration(milliseconds: 1234),
      headers: {'Content-Type': 'application/json', 'X-Request-ID': '12345'},
      contentLength: 2048,
      metadata: {'itemCount': 25, 'cached': false},
    );

    _showSnackBar('Network request logged');
  }

  void _logUserAction() {
    VooLogger.userAction(
      'button_click',
      screen: 'LoggingExamplePage',
      properties: {'button': 'log_user_action', 'timestamp': DateTime.now().toIso8601String(), 'sessionDuration': 300},
    );

    _showSnackBar('User action logged');
  }

  void _simulateError() {
    try {
      throw Exception('This is a simulated error for demonstration');
    } catch (e, stackTrace) {
      VooLogger.error(
        'An error occurred in the example app',
        error: e,
        stackTrace: stackTrace,
        category: 'Error',
        tag: 'SimulatedError',
        metadata: {'errorType': e.runtimeType.toString(), 'screen': 'LoggingExamplePage'},
      );
    }

    _showSnackBar('Error logged with stack trace');
  }

  void _logPerformance() {
    VooLogger.performance(
      'DatabaseQuery',
      const Duration(milliseconds: 456),
      metrics: {'rowCount': 1000, 'cacheHit': false, 'queryType': 'SELECT', 'table': 'users'},
    );

    _showSnackBar('Performance metric logged');
  }

  Future<void> _generateMultipleLogs() async {
    final categories = ['Network', 'Database', 'UI', 'Analytics', 'System'];
    const levels = LogLevel.values;

    for (int i = 0; i < 20; i++) {
      final category = categories[i % categories.length];
      final level = levels[i % levels.length];

      VooLogger.log(
        'Generated log #${i + 1}: Sample ${level.name} message',
        level: level,
        category: category,
        tag: 'BatchLog',
        metadata: {'index': i, 'batch': true, 'timestamp': DateTime.now().toIso8601String()},
      );
    }

    _showSnackBar('Generated 20 logs');
  }

  Future<void> _viewStatistics() async {
    final stats = await VooLogger.getStatistics();

    if (!mounted) return;

    await showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Log Statistics'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('Total Logs: ${stats.totalLogs}'),
            const SizedBox(height: 8),
            const Text('By Level:'),
            // ...stats.levelCounts.entries.map((e) => Text('  ${e.key}: ${e.value}')),
            const SizedBox(height: 8),
            const Text('By Category:'),
            // ...stats.categoryCounts.entries.take(5).map((e) => Text('  ${e.key}: ${e.value}')),
          ],
        ),
        actions: [TextButton(onPressed: () => Navigator.of(context).pop(), child: const Text('Close'))],
      ),
    );
  }

  Future<void> _exportLogs() async {
    final jsonLogs = await VooLogger.exportLogs();

    // In a real app, you would save this to a file
    debugPrint('Exported logs: ${jsonLogs.substring(0, 200)}...');

    _showSnackBar('Logs exported (check console)');
  }

  Future<void> _clearLogs() async {
    final confirmed = await showDialog<bool>(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Clear All Logs?'),
        content: const Text('This will delete all stored logs. This action cannot be undone.'),
        actions: [
          TextButton(onPressed: () => Navigator.of(context).pop(false), child: const Text('Cancel')),
          TextButton(
            onPressed: () => Navigator.of(context).pop(true),
            child: const Text('Clear', style: TextStyle(color: Colors.red)),
          ),
        ],
      ),
    );

    if (confirmed == true) {
      await VooLogger.clearLogs();
      _showSnackBar('All logs cleared');
    }
  }

  void _changeUser() {
    final newUserId = 'user_${DateTime.now().millisecondsSinceEpoch}';
    VooLogger.setUserId(newUserId);
    VooLogger.startNewSession();

    VooLogger.info('User changed', category: 'System', metadata: {'oldUserId': 'user123', 'newUserId': newUserId});

    _showSnackBar('User changed to: $newUserId');
  }

  void _showSnackBar(String message) {
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message)));
  }
}
6
likes
0
points
412
downloads

Publisher

unverified uploader

Weekly Downloads

A comprehensive logging package for Flutter and Dart applications with DevTools integration.

Homepage
Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

bloc, devtools_app_shared, devtools_extensions, equatable, flutter, flutter_bloc, json_annotation, path, path_provider, sembast, sembast_web, vm_service

More

Packages that depend on voo_logging