my_log 2.0.0 copy "my_log: ^2.0.0" to clipboard
my_log: ^2.0.0 copied to clipboard

Structured Flutter logging with redaction, rotating files, diagnostics, custom sinks, an in-app viewer, and a DevTools extension.

example/lib/main.dart

import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:my_log/my_log.dart';
import 'package:path_provider/path_provider.dart';

typedef DirectoryProvider = Future<Directory?> Function();

Future<Directory?> resolveAppDirectory({
  required TargetPlatform platform,
  required bool isWeb,
  required DirectoryProvider getDocumentsDirectory,
  required DirectoryProvider getDownloadsDirectory,
}) async {
  if (isWeb) {
    return null;
  }

  switch (platform) {
    case TargetPlatform.iOS:
    case TargetPlatform.macOS:
      return getDocumentsDirectory();
    case TargetPlatform.android:
    case TargetPlatform.linux:
    case TargetPlatform.windows:
      return getDownloadsDirectory();
    case TargetPlatform.fuchsia:
      return null;
  }
}

Future<String?> setUpLogging({
  required MyLog log,
  required TargetPlatform platform,
  required bool isWeb,
  required DirectoryProvider getDocumentsDirectory,
  required DirectoryProvider getDownloadsDirectory,
}) async {
  final appDir = await resolveAppDirectory(
    platform: platform,
    isWeb: isWeb,
    getDocumentsDirectory: getDocumentsDirectory,
    getDownloadsDirectory: getDownloadsDirectory,
  );

  if (appDir == null) {
    await log.configure(
      const MyLogConfig(captureFlutterErrors: true, maxHistoryEntries: 1000),
    );
    log.warning('File logging is unavailable; using console logging only.');
    return null;
  }

  final logPath = '${appDir.path}/my_log.jsonl';
  await log.configure(
    MyLogConfig(
      filePath: logPath,
      fileFormat: MyLogFileFormat.jsonLines,
      maxFileSizeBytes: 2 * 1024 * 1024,
      maxFiles: 4,
      retention: const Duration(days: 7),
      captureFlutterErrors: true,
      diagnosticMetadata: const <String, Object?>{
        'application': 'my_log example',
      },
    ),
    noteInfoFileLog: 'This is the log file for my Flutter app.',
  );
  log.infoEntry('App started', tag: 'lifecycle');

  return logPath;
}

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

  final logPath = await setUpLogging(
    log: myLog,
    platform: defaultTargetPlatform,
    isWeb: kIsWeb,
    getDocumentsDirectory: getApplicationDocumentsDirectory,
    getDownloadsDirectory: getDownloadsDirectory,
  );

  consoleLogController.setPathSaveLog(logPath);
  runApp(MyApp(logPath: logPath));
}

MyConsoleLogController consoleLogController = MyConsoleLogController();

class MyApp extends StatelessWidget {
  final String? logPath;
  const MyApp({super.key, required this.logPath});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // home: LogScreen(logPath: logPath),
      builder: (context, child) {
        return MyConsoleLog(
          controller: consoleLogController,
          log: myLog,
          children: [LogScreen(logPath: logPath)],
        );
      },
    );
  }
}

class LogScreen extends StatefulWidget {
  final String? logPath;
  const LogScreen({super.key, required this.logPath});

  @override
  LogScreenState createState() => LogScreenState();
}

class LogScreenState extends State<LogScreen> {
  String logContent = "";

  Future<void> readLogFile() async {
    final logPath = widget.logPath;
    if (logPath == null) {
      setState(() {
        logContent = 'File logging is unavailable on this platform.';
      });
      return;
    }
    try {
      final logFile = File(logPath);
      if (await logFile.exists()) {
        String content = await logFile.readAsString();
        setState(() {
          logContent = content;
        });
      } else {
        setState(() {
          logContent = "Log file not found.";
        });
      }
    } catch (e) {
      setState(() {
        logContent = "Error reading log file: \$e";
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flutter Logging Example')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const SizedBox(height: 20),
            const Text(
              "STEP 1: show log dialog",
              style: TextStyle(fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                consoleLogController.setShowConsoleLog(true);
              },
              child: const Text('Show realtime logs'),
            ),
            const SizedBox(height: 20),
            const Text(
              "STEP 2: create log",
              style: TextStyle(fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () async {
                myLog.traceEntry(
                  'Preparing checkout',
                  tag: 'payment',
                  flag: 'checkout',
                );
                myLog.infoEntry(
                  'Payment created',
                  tag: 'payment',
                  flag: 'checkout',
                  fields: const <String, Object?>{
                    'orderId': 'ORDER-42',
                    'amount': 199000,
                    'access_token': 'automatically-redacted',
                  },
                );
                myLog.debug(3);
                myLog.warning(4, tag: "Your tag", flag: "Your flag");
                myLog.error(5, tag: "Your tag", flag: "Your flag");
                myLog.fatal(6, error: "ERROR");
              },
              child: const Text('Press Me'),
            ),
            const SizedBox(height: 20),
            const Text(
              "STEP 3: save file log",
              style: TextStyle(fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 20),
            Text(
              widget.logPath == null
                  ? 'File logging is unavailable on this platform.'
                  : 'Log file saved at: ${widget.logPath}',
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: widget.logPath == null ? null : readLogFile,
              child: const Text('See logFile content'),
            ),
            const SizedBox(height: 20),
            Expanded(
              child: SingleChildScrollView(
                child: Text(logContent, style: const TextStyle(fontSize: 14)),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
4
likes
150
points
85
downloads
screenshot

Documentation

API reference

Publisher

verified publisherwongcoupon.com

Weekly Downloads

Structured Flutter logging with redaction, rotating files, diagnostics, custom sinks, an in-app viewer, and a DevTools extension.

Repository (GitHub)
View/report issues

Topics

#logging #color #save-file #popup-realtime-log #structured-logging

Funding

Consider supporting this project:

buymeacoffee.com
ko-fi.com

License

MIT (license)

Dependencies

archive, flutter, flutter_staggered_animations, gap, logger

More

Packages that depend on my_log