Flutter日志记录插件log_4_dart_2的使用

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

Flutter日志记录插件log_4_dart_2的使用

概述

log_4_dart_2 是一个用于高级日志记录的 Dart 包,支持多种可配置的追加器。

目录

前言

该包正在建设中,仍需要一些调整和代码改进!

安装

pubspec.yaml

pubspec.yaml 文件中更新并添加以下依赖项:

dependencies:
  log_for_dart_2: ^1.1.0

导入

导入包:

import 'package:log_4_dart_2/log_4_dart_2.dart';

使用

设置日志记录器

有以下两种方式来设置 Logger

  1. 将日志记录器配置存储在一个单独的 JSON 文件中,并将文件的完整路径传递给 initFromFile() 方法。
  2. 创建一个 Map<String, dynamic> 来保存配置,并将其传递给 init() 方法。
void main(List<String> arguments){
  // 从配置文件初始化日志记录器
  Logger.initFromFile('/path/to/log4d.json');
  // 或者通过 Map<String, dynamic>
  Logger.init(config);
}

注意,Logger.init(...) 只能调用一次,最好在主方法中调用。它会内部配置一个实例,可以通过静态 Logger(或 Logger.instance)访问。

查看示例配置获取完整的示例。

日志记录

Logger 提供了多个方法用于不同级别的日志记录。

static String TAG = 'TestClass';
Logger.debug('Lorem Ipsum', tag: TAG);
Logger.trace('Lorem Ipsum', tag: TAG);
Logger.info('Lorem Ipsum', tag: TAG);
Logger.warn('Lorem Ipsum', tag: TAG);
Logger.error('Lorem Ipsum', tag: TAG);
Logger.fatal('Lorem Ipsum', tag: TAG);

注意,从版本 1.0.0 开始,旧的方式需要稍作修改:Logger().debug(...) 现在应称为 Logger().logDebug(...)(相应级别)。

以下是两种被认为是客户端上下文中最佳的日志记录方式:

1: 通过 Logger 类上的静态日志方法直接记录:

class PlainClient {
  void doStuff() {
    Logger.debug('message', tag: 'some tag');
  }
}

2: 通过 Log4Dart 混入。注意,这里的日志方法被称为 logDebug(...) 等,以明确其来自客户端代码。

class Client with Log4Dart {
  void doStuff() {
    logDebug('message', tag: 'some tag');
  }
}

注意,在这两种情况下,都需要先初始化 Logger,例如在主方法中:

void main() async {
   await Logger.init(kLog4DartConfig);
   ...
}

追加器和配置

ConsoleAppender

ConsoleAppender 是一个简单的追加器,将每个日志条目追加到控制台输出。

  • type: 追加器类型,必须设置为 CONSOLE
  • dateFormat: 用于追加器的日期格式,默认为 yyyy-MM-dd HH:mm:ss
  • level: 该追加器的日志级别。
  • format: 日志输出的格式。参见日志格式了解更多。
  • brackets: 是否用括号包裹所有消息块,消息不包括在内。

FileAppender

FileAppender 将每个日志条目追加到日志文件。

  • type: 追加器类型,必须设置为 FILE
  • level: 该追加器的日志级别。
  • format: 日志输出的格式。参见日志格式了解更多。
  • dateFormat: 用于追加器的日期格式,默认为 yyyy-MM-dd HH:mm:ss
  • filePattern: 用于文件名的模式。
  • fileExtension: 文件扩展名,默认为 log
  • path: 文件路径。
  • rotationCycle: 追加器的旋转周期。参见旋转周期。默认为 NEVER

注意:如果指定了路径,路径也必须存在!

HttpAppender

HttpAppender 通过 HTTP POST 请求将日志条目发送到指定 URL。

  • type: 追加器类型,必须设置为 HTTP
  • dateFormat: 用于追加器的日期格式,默认为 yyyy-MM-dd HH:mm:ss
  • level: 该追加器的日志级别。
  • url: POST 请求的 URL。
  • headers: 一个包含头名称和值的列表,名称和值由 : 分隔。例如 "Content-Type:application/json"

EmailAppender

EmailAppender 通过电子邮件将日志条目发送到指定地址。

  • type: 追加器类型,必须设置为 EMAIL
  • dateFormat: 用于追加器的日期格式,默认为 yyyy-MM-dd HH:mm:ss
  • level: 该追加器的日志级别。
  • host: SMTP 服务器。
  • user: 服务器的用户。
  • password: 给定用户的密码。
  • port: SMTP 服务器的端口。
  • fromMail: 发送者的电子邮件。默认使用用户名。
  • fromName: 发送者的名称。
  • to: 要发送邮件的电子邮件地址列表。
  • toCC: 要接收副本的电子邮件地址列表。
  • toBCC: 要接收盲副本的电子邮件地址列表。
  • ssl: 是否使用 SSL。
  • templateFile: 包含要使用的模板的文件的完整路径。如果没有提供模板,追加器将发送 JSON 格式的日志记录。可以使用与格式设置相同的占位符。参见日志格式了解更多。
  • html: 给定模板是否为纯文本或 HTML。默认为 false

注意:由于使用了 mailer 包来提供此追加器,这仅适用于需要用户/密码授权的邮件服务器。

MySqlAppender

MySqlAppender 将每个日志条目追加到 MySQL 数据库的表中。

  • type: 追加器类型,必须设置为 MYSQL
  • level: 该追加器的日志级别。
  • host: MySQL 数据库的主机。
  • user: 用户。
  • password: 用户的密码。
  • port: 主机的端口。
  • database: 数据库名称。
  • table: 要写入的表。

创建表时使用给定的语句。替换 <table> 为你所需的表名。

CREATE TABLE `$table` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `tag` VARCHAR(45) NULL,
  `level` VARCHAR(45) NULL,
  `message` VARCHAR(45) NULL,
  `time` VARCHAR(45) NULL,
  PRIMARY KEY (`id`));

添加自定义追加器

Log4Dart2 支持使用自定义追加器。创建一个继承自 Appender 并实现 appendinit 方法的类。

import 'package:log_4_dart_2/log_4_dart_2.dart';

class CustomAppender extends Appender {
  @override
  void append(LogRecord logRecord) {
    // 实现 append 方法
  }

  @override
  void init(Map<String, dynamic> config, bool test, DateTime date) {
    // 实现 init 方法
  }

  @override
  Appender getInstance(){
    return CustomAppender();
  }

  @override
  String getType(){
    return 'CustomAppender';
  }
}

在日志记录器初始化之前,通过 registerAppender() 方法注册自定义追加器。

Logger.instance.registerAppender(CustomAppender());

日志格式

可以为某些追加器配置日志条目的格式。

  • %d: 日期。
  • %i: 标识符。
  • %t: 标签。
  • %l: 日志级别。
  • %m: 消息。
  • %f: 包含行号和列号的文件名(例如 package:my_project/chat_screen.dart(42:7))。
  • %c: 包含行号的方法名和类名(例如 ChatScreenState.getCurrentUser:42)。

当应用程序在 Zone 中运行时,还可以添加 MDC(映射诊断上下文)占位符:

  • %X{

最好通过一个例子来展示:

void main() async {
   await Logger.init(kLog4DartConfig);
  
   // 我们定义 zone 的值作为第 3 个参数:zoneValues
   // 这不能在测试回调中运行,目前这可以在直接运行或进一步执行...
   await runZonedGuarded(() async {
      // 应用程序运行时,我们在某个地方将一些变量设置到 zone:
      if (Zone.current['LOG_SESSION_HASH_KEY'] != null) {
         // 将 LOG_SESSION_HASH_KEY 设置为 865a15
         Zone.current['LOG_SESSION_HASH_KEY'].add(generateMd5Fingerprint('Some data like app start timestamp'));
      }
      // 然后我们记录并交由日志库处理
      Logger.debug('hello world');
      }, (Object error, StackTrace stackTrace) {
         print(error);
      }, zoneValues: {
         // 将 LOG_DEVICE_HASH_KEY 设置为 8634e3c65a15
         'LOG_DEVICE_HASH_KEY': [generateMd5Fingerprint('Data that is consistent per platform like values delivered by device_info_plus')],
         'vLOG_SESSION_HASH_KEY': [], // 当前为空,进一步设置
      });
   }
   
   // 只是一个想法...
   String generateMd5Fingerprint(String input) {
      return md5.convert(utf8.encode(input)).toString().substring(0, 6);
   }
}

使用此格式设置:

'format': '%d%i%X{logging.device-hash}%X{logging.session-hash}%t%l%c %m %f'

应该打印类似以下内容,其中两个部分 [634e3c][865a15] 对于日志分析非常有用:

 [2022-04-28 14:44:26.934][CONSOLE][634e3c][865a15][tag-512][DEBUG][ClientWithLogEx.logStuff:60] hello world [package:my_project/chat_screen.dart(60:5)]

示例:

  • "%d %i %t %l %m"
  • "This log entry was created on %d from class %t from thread %i. It has the level %l and the message %m"

HTML 模板示例:

<h1>Log Event</h1>
<p>Message: %m</p>
<p>Class: %t</p>
<p>Time: %d</p>
<p>Level: %l</p>

旋转周期

旋转周期可以为某些追加器配置。它定义了创建新文件以存储日志数据的频率。

  • NEVER (永不旋转)
  • DAY (每日旋转)
  • WEEK (每周旋转)
  • MONTH (每月旋转,每个月的第一天)
  • YEAR (每年旋转,每年的第一天)

示例配置

以下是带有所有可能追加器及其设置的一些配置示例。

var config = {
  'appenders': [
    {
      'type': 'CONSOLE',
      'format': '%d%i%t%l%c %m %f',
      'level': 'TRACE',
      'dateFormat': 'yyyy-MM-dd HH:mm:ss.SSS',
      'brackets': true,
      'mode': 'stdout'
    },
    {
      'type': 'FILE',
      'dateFormat' : 'yyyy-MM-dd HH:mm:ss',
      'format': '%d %i %t %l %m',
      'level': 'INFO',
      'filePattern': 'log4dart2_log',
      'fileExtension': 'txt',
      'path': '/path/to/',
      'rotationCycle': 'MONTH'
    },
    {
      'type': 'EMAIL',
      'dateFormat' : 'yyyy-MM-dd HH:mm:ss',
      'level': 'INFO',
      'host': 'smtp.test.de',
      'user': 'test@test.de',
      'password': 'test',
      'port': 1,
      'fromMail': 'test@test.de',
      'fromName': 'Jon Doe',
      'to': [
        'test1@example.com',
        'test2@example.com'
      ],
      'toCC': [
        'test1@example.com',
        'test2@example.com'
      ],
      'toBCC': [
        'test1@example.com',
        'test2@example.com'
      ],
      'ssl': true,
      'templateFile': '/path/to/template.txt',
      'html': false
    },
    {
      'type': 'HTTP',
      'dateFormat' : 'yyyy-MM-dd HH:mm:ss',
      'level': 'INFO',
      'url': 'api.example.com',
      'headers': [
        'Content-Type:application/json'
      ]
    },
    {
      'type': 'MYSQL',
      'level': 'INFO',
      'host': 'database.example.com',
      'user': 'root',
      'password': 'test',
      'port': 1,
      'database': 'mydatabase',
      'table' : 'log_entries'
    }
  ]
};
{
  "appenders": [
    {
      "type": "CONSOLE",
      "dateFormat" : "yyyy-MM-dd HH:mm:ss",
      "format": "%d %i %t %l %m",
      "level": "INFO"
    },
    {
      "type": "FILE",
      "dateFormat" : "yyyy-MM-dd HH:mm:ss",
      "format": "%d %i %t %l %m",
      "level": "INFO",
      "filePattern": "log4dart2_log",
      "fileExtension": "txt",
      "path": "/path/to/",
      "rotationCycle": "MONTH"
    },
    {
      "type": "EMAIL",
      "dateFormat" : "yyyy-MM-dd HH:mm:ss",
      "level": "INFO",
      "host": "smtp.test.de",
      "user": "test@test.de",
      "password": "test",
      "port": 1,
      "fromMail": "test@test.de",
      "fromName": "Jon Doe",
      "to": [
        "test1@example.com",
        "test2@example.com"
      ],
      "toCC": [
        "test1@example.com",
        "test2@example.com"
      ],
      "toBCC": [
        "test1@example.com",
        "test2@example.com"
      ],
      "ssl": true,
      "templateFile": "/path/to/template.txt",
      "html": false
    },
    {
      "type": "HTTP",
      "dateFormat" : "yyyy-MM-dd HH:mm:ss",
      "level": "INFO",
      "url": "api.example.com",
      "headers": [
        "Content-Type:application/json"
      ]
    },
    {
      "type": "MYSQL",
      "level": "INFO",
      "host": "database.example.com",
      "user": "root",
      "password": "test",
      "port": 1,
      "database": "mydatabase",
      "table" : "log_entries"
    }
  ]
}

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

1 回复

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


当然,以下是如何在Flutter项目中使用log_4_dart_2插件进行日志记录的示例代码。log_4_dart_2是一个流行的日志记录库,可以帮助你更好地管理和记录应用程序中的日志信息。

首先,确保你已经在pubspec.yaml文件中添加了log_4_dart_2依赖:

dependencies:
  flutter:
    sdk: flutter
  log_4_dart_2: ^x.y.z  # 请将x.y.z替换为实际的版本号

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

接下来,在你的Flutter项目中,你可以按照以下步骤使用log_4_dart_2进行日志记录:

  1. 导入包

在你的Dart文件中导入log_4_dart_2包。

import 'package:log_4_dart_2/log_4_dart_2.dart';
  1. 配置日志记录器

在应用程序的入口点(通常是main.dart文件)中配置日志记录器。

void main() {
  // 配置日志记录器
  var logger = Logger('MyAppLogger');
  logger.level = LogLevel.DEBUG; // 设置日志级别
  logger.addAppender(
    ConsoleAppender()..layout = PatternLayout(pattern: '[%d] [%p] %c: %m%n'),
  );

  // 运行应用程序
  runApp(MyApp());
}
  1. 记录日志

在你的应用程序中记录不同级别的日志。

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

void main() {
  var logger = Logger('MyAppLogger');
  logger.level = LogLevel.DEBUG;
  logger.addAppender(
    ConsoleAppender()..layout = PatternLayout(pattern: '[%d] [%p] %c: %m%n'),
  );

  runApp(MyApp(logger: logger));
}

class MyApp extends StatelessWidget {
  final Logger logger;

  MyApp({required this.logger});

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

class MyHomePage extends StatefulWidget {
  final Logger logger;

  MyHomePage({required this.logger});

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

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    super.initState();
    // 记录不同级别的日志
    widget.logger.debug('This is a debug message');
    widget.logger.info('This is an info message');
    widget.logger.warn('This is a warning message');
    widget.logger.error('This is an error message');
    widget.logger.fatal('This is a fatal message');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Demo Home Page'),
      ),
      body: Center(
        child: Text('Check your console for log messages'),
      ),
    );
  }
}

在这个示例中,我们创建了一个全局的Logger实例,并在应用程序的入口点配置了它。然后,在MyHomePage组件的initState方法中,我们记录了不同级别的日志消息。这些日志消息将按照配置的格式输出到控制台。

请注意,log_4_dart_2插件的具体API和使用方式可能会根据版本的不同而有所变化。因此,建议查阅该插件的官方文档以获取最新和最准确的信息。

回到顶部