Flutter日志管理插件flutter_logs的使用

发布于 1周前 作者 zlyuanteng 来自 Flutter

Flutter日志管理插件flutter_logs的使用

概述

flutter_logs 是一个基于文件的高级日志记录框架,适用于Flutter应用程序(Android & iOS)。该插件可以将所有日志保存到指定的存储路径中。每小时会创建一个新的日志文件,并且可以根据需要过滤和排序这些日志。此外,日志可以导出为压缩包,并支持自定义日志格式、加密等功能。

功能特性

Android 特性

  • 每小时生成的日志文件
  • 文件压缩与导出
  • 清除日志功能
  • 自定义日志格式
  • CSV 支持
  • 自定义时间戳
  • 多目录结构
  • 加密支持
  • 实时发送日志至服务器(MQTT)

iOS 特性

  • 日志文件生成与管理
  • 文件压缩与导出
  • 清除日志功能

安装与配置

依赖添加

pubspec.yaml 文件中添加依赖:

dependencies:
  flutter_logs: [Latest_Version]

初始化设置

main.dart 文件中初始化日志模块:

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  await FlutterLogs.initLogs(
    logLevelsEnabled: [
      LogLevel.INFO,
      LogLevel.WARNING,
      LogLevel.ERROR,
      LogLevel.SEVERE
    ],
    timeStampFormat: TimeStampFormat.TIME_FORMAT_READABLE,
    directoryStructure: DirectoryStructure.FOR_DATE,
    logTypesEnabled: ["device", "network", "errors"],
    logFileExtension: LogFileExtension.LOG,
    logsWriteDirectoryName: "MyLogs",
    logsExportDirectoryName: "MyLogs/Exported",
    debugFileOperations: true,
    isDebuggable: true,
    logsRetentionPeriodInDays: 14,
    zipsRetentionPeriodInDays: 3,
    autoDeleteZipOnExport: false,
    autoClearLogs: true,
    enabled: true,
  );

  runApp(MyApp());
}

日志记录方法

普通日志记录

FlutterLogs.logInfo("TAG", "subTag", "My Log Message");
FlutterLogs.logWarn("TAG", "subTag", "My Log Message");
FlutterLogs.logError("TAG", "subTag", "My Log Message");
FlutterLogs.logErrorTrace("TAG", "subTag", "My Log Message", Error());

自定义文件日志记录

await FlutterLogs.initLogs(logTypesEnabled: ["Locations", "Jobs", "API"]);
FlutterLogs.logToFile(
  logFileName: "Locations",
  overwrite: false,
  logMessage: "{0.0,0.0}",
);

日志导出与打印

导出所有日志

FlutterLogs.exportLogs(exportType: ExportType.ALL);

打印所有日志

FlutterLogs.printLogs(exportType: ExportType.ALL);

导出自定义文件日志

FlutterLogs.exportFileLogForName(logFileName: "Locations");

打印自定义文件日志

FlutterLogs.printFileLogForName(logFileName: "Locations");

监听导出结果

FlutterLogs.channel.setMethodCallHandler((call) async {
  if (call.method == 'logsExported') {
    var zipName = "${call.arguments.toString()}";
    // 获取外部存储路径并检查文件是否存在
    // ...
  } else if (call.method == 'logsPrinted') {
    // 获取打印结果
  }
});

清除日志

FlutterLogs.clearLogs();

异常日志记录

try {
  var i = 100 ~/ 0;
  print("$i");
} catch (e) {
  FlutterLogs.logThis(
    tag: 'MyApp',
    subTag: 'Caught an exception.',
    logMessage: 'Caught an exception!',
    exception: e,
    level: LogLevel.ERROR,
  );
}

ELK Elastic Stack Schema 支持

await FlutterLogs.setMetaInfo(
  appId: "flutter_logs_example",
  appName: "Flutter Logs Demo",
  appVersion: "1.0",
  language: "en-US",
  deviceId: "00012",
  environmentId: "7865",
  environmentName: "dev",
  organizationId: "5767",
  userId: "883023-2832-2323",
  userName: "umair13adil",
  userEmail: "m.umair.adil@gmail.com",
  deviceSerial: "YJBKKSNKDNK676",
  deviceBrand: "LG",
  deviceName: "LG-Y08",
  deviceManufacturer: "LG",
  deviceModel: "989892BBN",
  deviceSdkInt: "26",
  latitude: "0.0",
  longitude: "0.0",
  labels: "",
);

MQTT 支持

await FlutterLogs.initMQTT(
  topic: "YOUR_TOPIC",
  brokerUrl: "", // URL 不包含协议头
  certificate: "assets/m2mqtt_ca.crt",
  port: "8883",
  writeLogsToLocalStorage: true,
  debug: true,
  initialDelaySecondsForPublishing: 10,
);

示例代码

以下是一个完整的示例代码,展示了如何在Flutter应用中使用flutter_logs进行日志管理:

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_logs/flutter_logs.dart';
import 'package:path_provider/path_provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  var _tag = "MyApp";
  var _myLogFileName = "MyLogFile";
  var toggle = false;
  var logStatus = '';
  static Completer<String> _completer = Completer<String>();

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

  void setUpLogs() async {
    await FlutterLogs.initLogs(
      logLevelsEnabled: [
        LogLevel.INFO,
        LogLevel.WARNING,
        LogLevel.ERROR,
        LogLevel.SEVERE
      ],
      timeStampFormat: TimeStampFormat.TIME_FORMAT_READABLE,
      directoryStructure: DirectoryStructure.FOR_DATE,
      logTypesEnabled: [_myLogFileName],
      logFileExtension: LogFileExtension.LOG,
      logsWriteDirectoryName: "MyLogs",
      logsExportDirectoryName: "MyLogs/Exported",
      debugFileOperations: true,
      isDebuggable: true,
      enabled: true,
    );

    FlutterLogs.logInfo(_tag, "setUpLogs", "Setting up logs...");

    FlutterLogs.channel.setMethodCallHandler((call) async {
      if (call.method == 'logsExported') {
        setLogsStatus(status: "logsExported: ${call.arguments.toString()}", append: true);
        _completer.complete(call.arguments.toString());
      } else if (call.method == 'logsPrinted') {
        setLogsStatus(status: "logsPrinted: ${call.arguments.toString()}", append: true);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Flutter Logs')),
        body: Center(
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: Column(
              children: [
                Center(child: Text(logStatus, maxLines: 10)),
                SizedBox(height: 20),
                ElevatedButton(onPressed: () => logData(isException: false), child: Text('Log Something', style: TextStyle(fontSize: 20))),
                ElevatedButton(onPressed: () => logData(isException: true), child: Text('Log Exception', style: TextStyle(fontSize: 20))),
                ElevatedButton(onPressed: logToFile, child: Text('Log To File', style: TextStyle(fontSize: 20))),
                ElevatedButton(onPressed: printAllLogs, child: Text('Print All Logs', style: TextStyle(fontSize: 20))),
                ElevatedButton(onPressed: () => exportAllLogs().then((value) async {
                  Directory? externalDirectory;
                  if (Platform.isIOS) {
                    externalDirectory = await getApplicationDocumentsDirectory();
                  } else {
                    externalDirectory = await getExternalStorageDirectory();
                  }
                  File file = File("${externalDirectory!.path}/$value");
                  if (file.existsSync()) {
                    setLogsStatus(status: "All logs exported to: \n\nPath: ${file.path}");
                  } else {
                    setLogsStatus(status: "File not found in storage.");
                  }
                }), child: Text('Export All Logs', style: TextStyle(fontSize: 20))),
                ElevatedButton(onPressed: printFileLogs, child: Text('Print File Logs', style: TextStyle(fontSize: 20))),
                ElevatedButton(onPressed: exportFileLogs, child: Text('Export File Logs', style: TextStyle(fontSize: 20))),
                ElevatedButton(onPressed: () {
                  FlutterLogs.clearLogs();
                  setLogsStatus(status: "");
                }, child: Text('Clear Logs', style: TextStyle(fontSize: 20))),
              ],
            ),
          ),
        ),
      ),
    );
  }

  void logData({required bool isException}) {
    var logMessage = 'This is a log message: ${DateTime.now().millisecondsSinceEpoch}';
    if (!isException) {
      FlutterLogs.logInfo(_tag, 'logData', logMessage);
    } else {
      try {
        if (toggle) {
          toggle = false;
          var i = 100 ~/ 0;
          print(i);
        } else {
          toggle = true;
          dynamic i;
          print(i * 10);
        }
      } catch (e) {
        if (e is Error) {
          FlutterLogs.logError(_tag, 'Caught an error.', 'Caught an exception!', error: e);
          logMessage = e.stackTrace.toString();
        } else if (e is Exception) {
          FlutterLogs.logError(_tag, 'Caught an exception.', 'Caught an exception!', exception: e);
          logMessage = e.toString();
        }
      }
    }
    setLogsStatus(status: logMessage);
  }

  void logToFile() {
    var logMessage = "This is a log message: ${DateTime.now().millisecondsSinceEpoch}, it will be saved to my log file named: '$_myLogFileName'";
    FlutterLogs.logToFile(
      logFileName: _myLogFileName,
      overwrite: false,
      logMessage: logMessage,
      appendTimeStamp: true,
    );
    setLogsStatus(status: logMessage);
  }

  void printAllLogs() {
    FlutterLogs.printLogs(exportType: ExportType.ALL, decryptBeforeExporting: true);
    setLogsStatus(status: "All logs printed");
  }

  Future<String> exportAllLogs() async {
    FlutterLogs.exportLogs(exportType: ExportType.ALL);
    return _completer.future;
  }

  void exportFileLogs() {
    FlutterLogs.exportFileLogForName(logFileName: _myLogFileName, decryptBeforeExporting: true);
  }

  void printFileLogs() {
    FlutterLogs.printFileLogForName(logFileName: _myLogFileName, decryptBeforeExporting: true);
  }

  void setLogsStatus({String status = '', bool append = false}) {
    setState(() {
      if (append) {
        logStatus += "\n$status";
      } else {
        logStatus = status;
      }
    });
  }
}

通过上述代码,您可以快速上手并集成flutter_logs插件到您的Flutter项目中,实现强大的日志管理功能。


更多关于Flutter日志管理插件flutter_logs的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter日志管理插件flutter_logs的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用flutter_logs插件进行日志管理的代码示例。flutter_logs是一个用于捕获、处理和发送Flutter应用日志的插件。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加flutter_logs依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_logs: ^x.y.z  # 请将x.y.z替换为最新版本号

然后运行flutter pub get来安装依赖。

2. 初始化flutter_logs

在你的应用的主入口文件(通常是main.dart)中初始化flutter_logs

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

void main() {
  // 初始化 Flutter Logs
  FlutterLogs.instance.init(
    // 设置日志级别,例如:DEBUG, INFO, WARN, ERROR
    logLevel: LogLevel.DEBUG,
    // 设置日志输出目标,例如:CONSOLE, FILE, REMOTE
    logTargets: [LogTarget.CONSOLE, LogTarget.FILE],
    // 如果使用 FILE 作为日志目标,设置日志文件路径
    filePath: 'logs/app_logs.txt',
    // 如果使用 REMOTE 作为日志目标,设置相关配置(这里省略)
  );

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    super.initState();
    // 示例日志
    FlutterLogs.instance.d('这是一条调试日志');
    FlutterLogs.instance.i('这是一条信息日志');
    FlutterLogs.instance.w('这是一条警告日志');
    FlutterLogs.instance.e('这是一条错误日志');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Logs Demo'),
      ),
      body: Center(
        child: Text('查看控制台和日志文件以查看日志'),
      ),
    );
  }
}

3. 查看日志

  • 控制台日志:在开发过程中,日志会输出到开发工具的控制台(如Android Studio、VSCode的控制台)。
  • 文件日志:日志会被写入到你指定的文件路径中(如上述示例中的logs/app_logs.txt)。在Android设备上,你可以通过ADB工具访问这些日志文件;在iOS设备上,你可以通过Xcode的Devices窗口访问应用的沙盒目录。

4. 清理和配置

你可以根据需求进一步配置flutter_logs,例如设置日志文件的最大大小、日志的格式化方式等。具体配置请参考flutter_logs的官方文档和API。

注意事项

  • 确保你有适当的权限来写入日志文件(特别是在Android和iOS设备上)。
  • 根据应用的需求,谨慎选择日志级别和目标,以避免不必要的性能开销和数据泄露。

这样,你就可以在Flutter应用中使用flutter_logs进行日志管理了。希望这个示例对你有所帮助!

回到顶部