voo_logging 0.0.1 copy "voo_logging: ^0.0.1" to clipboard
voo_logging: ^0.0.1 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(
    minimumLevel: LogLevel.verbose,
    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) {
    return 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) {
    return 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() {
    return 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) {
                      return 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) {
                      return 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() {
    return 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() {
    return 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() {
    return 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(),
      },
    );

    // Simulate network delay
    await Future.delayed(const Duration(seconds: 1));

    // 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');
  }

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

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

      await 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(),
        },
      );

      // Small delay to spread out timestamps
      await Future.delayed(const Duration(milliseconds: 50));
    }

    _showSnackBar('Generated 20 logs');
  }

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

    if (!mounted) return;

    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
584
downloads

Publisher

verified publishervoostack.com

Weekly Downloads

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

Homepage
Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

equatable, flutter, json_annotation, path, path_provider, sembast, sembast_web

More

Packages that depend on voo_logging