flex_logger_file 1.0.0 copy "flex_logger_file: ^1.0.0" to clipboard
flex_logger_file: ^1.0.0 copied to clipboard

File logging provider for FlexLogger - writes logs to local files with rotation support

example/lib/main.dart

import 'package:flex_logger/flex_logger.dart';
import 'package:flex_logger_file/flex_logger_file.dart';
import 'package:flutter/material.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';

/// File logging strategies available in the example.
enum StrategyType {
  rotating('Rotating Files', 'Size-based rotation (recommended)'),
  singleFile('Single File', 'One file with optional cleanup'),
  timeBased('Time-based', 'Daily log files')
  ;

  final String label;
  final String description;

  const StrategyType(this.label, this.description);
}

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

  final appDocDir = await getApplicationDocumentsDirectory();
  final logDir = path.join(appDocDir.path, 'logs');
  final logPath = path.join(logDir, 'example_app.log');

  // Using rotating file strategy (recommended for production)
  FlexLogger.instance.configure(
    providers: [
      FileLoggerProvider.rotating(
        filePath: logPath,
        maxFileSize: 2 * 1024 * 1024, // 2 MB per file
        maxBackupCount: 5, // Keep 5 backup files
        filter: const MinLevelFilter(FlexLogLevel.debug),
      ),
    ],
  );
  await FlexLogger.instance.initialize();

  FlexLogger.instance.info('Flex Logger File example started');
  FlexLogger.instance.debug('Logs are written to file');

  runApp(MyApp(logDir: logDir, logPath: logPath));
}

class MyApp extends StatelessWidget {
  final String logDir;
  final String logPath;

  const MyApp({super.key, required this.logDir, required this.logPath});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flex Logger File Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.green),
        useMaterial3: true,
      ),
      home: MyHomePage(
        title: 'File Example',
        logDir: logDir,
        logPath: logPath,
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;
  final String logDir;
  final String logPath;

  const MyHomePage({
    super.key,
    required this.title,
    required this.logDir,
    required this.logPath,
  });

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  StrategyType _selectedStrategy = StrategyType.rotating;

  @override
  void dispose() {
    // CRITICAL: Always dispose logger before app terminates
    FlexLogger.instance.dispose();
    super.dispose();
  }

  Future<void> _reconfigureLogger() async {
    await FlexLogger.instance.dispose();

    final providers = <LoggerProvider>[];

    // Add file provider based on selected strategy
    switch (_selectedStrategy) {
      case StrategyType.rotating:
        providers.add(
          FileLoggerProvider.rotating(
            filePath: widget.logPath,
            maxFileSize: 2 * 1024 * 1024, // 2 MB per file
            maxBackupCount: 5,
            filter: const MinLevelFilter(FlexLogLevel.debug),
          ),
        );
      case StrategyType.singleFile:
        providers.add(
          FileLoggerProvider.singleFile(
            filePath: widget.logPath,
            maxFileSize: 5 * 1024 * 1024, // 5 MB limit
            maxAge: const Duration(days: 7), // Keep logs for 7 days
            filter: const MinLevelFilter(FlexLogLevel.debug),
          ),
        );
      case StrategyType.timeBased:
        providers.add(
          FileLoggerProvider.timeBased(
            directoryPath: widget.logDir,
            filePrefix: 'app',
            maxAge: const Duration(days: 30), // Keep 30 days
            maxFiles: 30, // Or max 30 files
            filter: const MinLevelFilter(FlexLogLevel.debug),
          ),
        );
    }

    FlexLogger.instance.configure(providers: providers);
    await FlexLogger.instance.initialize();

    FlexLogger.instance.info(
      'Logger reconfigured with ${_selectedStrategy.label} strategy',
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: SingleChildScrollView(
          padding: const EdgeInsets.all(24.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text(
                'Logs are written to file',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
                textAlign: TextAlign.center,
              ),
              const SizedBox(height: 8),
              Text(
                'Current path: ${widget.logPath}',
                style: Theme.of(context).textTheme.bodySmall,
                textAlign: TextAlign.center,
              ),
              const SizedBox(height: 24),

              // Strategy selection
              _buildStrategySection(),

              const SizedBox(height: 24),
              const Divider(),
              const SizedBox(height: 16),

              // All log levels
              const Text(
                'Test All Log Levels:',
                style: TextStyle(fontWeight: FontWeight.w600),
              ),
              const SizedBox(height: 12),
              Wrap(
                spacing: 8,
                runSpacing: 8,
                alignment: WrapAlignment.center,
                children: [
                  ElevatedButton(
                    onPressed: () => FlexLogger.instance.debug('Debug from button'),
                    child: const Text('Debug'),
                  ),
                  ElevatedButton(
                    onPressed: () => FlexLogger.instance.info('Info from button'),
                    child: const Text('Info'),
                  ),
                  ElevatedButton(
                    onPressed: () => FlexLogger.instance.success('Success from button'),
                    child: const Text('Success'),
                  ),
                  ElevatedButton(
                    onPressed: () => FlexLogger.instance.warning('Warning from button'),
                    child: const Text('Warning'),
                  ),
                  ElevatedButton(
                    onPressed: () => FlexLogger.instance.error('Error from button'),
                    child: const Text('Error'),
                  ),
                  ElevatedButton(
                    onPressed: () => FlexLogger.instance.critical('Critical from button'),
                    child: const Text('Critical'),
                  ),
                ],
              ),

              const SizedBox(height: 16),

              // Exception handling
              ElevatedButton.icon(
                onPressed: () {
                  try {
                    throw Exception('Demo exception for file logging');
                  } catch (e, st) {
                    FlexLogger.instance.error('Error with exception', e, st);
                  }
                },
                icon: const Icon(Icons.bug_report),
                label: const Text('Log Error with Exception'),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildStrategySection() {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text(
              'File Strategy:',
              style: TextStyle(fontWeight: FontWeight.w600, fontSize: 16),
            ),
            const SizedBox(height: 12),

            // Strategy dropdown
            DropdownButton<StrategyType>(
              value: _selectedStrategy,
              isExpanded: true,
              items: StrategyType.values
                  .map(
                    (strategy) => DropdownMenuItem(
                      value: strategy,
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          Text(
                            strategy.label,
                            style: const TextStyle(fontWeight: FontWeight.w500),
                          ),
                          Text(
                            strategy.description,
                            style: Theme.of(context).textTheme.bodySmall,
                          ),
                        ],
                      ),
                    ),
                  )
                  .toList(),
              onChanged: (value) {
                if (value != null) {
                  setState(() => _selectedStrategy = value);
                }
              },
            ),

            const SizedBox(height: 16),

            // Apply button
            ElevatedButton.icon(
              onPressed: _reconfigureLogger,
              icon: const Icon(Icons.refresh),
              label: const Text('Apply Strategy'),
            ),

            const SizedBox(height: 12),

            // Info about current strategy
            Container(
              padding: const EdgeInsets.all(12),
              decoration: BoxDecoration(
                color: Theme.of(context).colorScheme.surfaceContainerHighest,
                borderRadius: BorderRadius.circular(8),
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    'Current: ${_selectedStrategy.label}',
                    style: const TextStyle(fontWeight: FontWeight.w500),
                  ),
                  const SizedBox(height: 4),
                  Text(
                    _getStrategyInfo(),
                    style: Theme.of(context).textTheme.bodySmall,
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  String _getStrategyInfo() {
    return switch (_selectedStrategy) {
      StrategyType.rotating => 'Files rotate at 2 MB. Keeps 5 backups (~12 MB total).',
      StrategyType.singleFile => 'Single file with 5 MB limit and 7-day age limit.',
      StrategyType.timeBased => 'New file each day. Keeps 30 days or 30 files.',
    };
  }
}
0
likes
0
points
279
downloads

Publisher

verified publisherkrajna.dev

Weekly Downloads

File logging provider for FlexLogger - writes logs to local files with rotation support

Homepage
Repository (GitLab)
View/report issues

Topics

#logging #file-logging #persistence #log-rotation

License

unknown (license)

Dependencies

flex_logger, flutter, path, path_provider

More

Packages that depend on flex_logger_file