flutter开发实战-日志logger写入文件及print
在开发中,需要日志logger写入文件,方便日后查看出现的问题。这里记录之前的实现方案。
使用的日志插件是logger
一、引入日志插件
在工程中pubspec.yaml引入logger
logger: ^1.4.0
二、代码实现
使用比较简单,只需创建一个Logger实例并开始日志记录:
var logger = Logger();
logger.d("Logger is working!");
也可以传递其他对象,如List、Map或Set,而不是字符串消息。
2.1 日志logger_manager
- 使用logger时候,配置logger
FileOutput fileOutPut = FileOutput();
ConsoleOutput consoleOutput = ConsoleOutput();
List<LogOutput> multiOutput = [fileOutPut, consoleOutput];
logger = Logger(
filter: DevelopmentFilter(),
// Use the default LogFilter (-> only log in debug mode)
// printer: SimplePrinter(
// colors: true,
// printTime: true,
// ),
printer: HybridPrinter(
PrettyPrinter(
noBoxingByDefault: false,
methodCount: 2,
// number of method calls to be displayed
errorMethodCount: 8,
// number of method calls if stacktrace is provided
lineLength: 120,
// width of the output
colors: true,
// Colorful log messages
printEmojis: false,
// Print an emoji for each log message
printTime: true, // Should each log print contain a timestamp
),
debug: SimplePrinter(),
),
- 写入文件的FileOutPut,其中用到了IOSink
IOSink可以方便将字节和文本输出,IOSink将字节的StreamSsink与StringSink组合,并且允许容易地输出字节和文本。
/// Writes the log output to a file.
class FileOutput extends LogOutput {
final bool overrideExisting;
final Encoding encoding;
IOSink? _sink;
File? file;
String? _currentDate;
FileOutput({
this.overrideExisting = false,
this.encoding = utf8,
});
Future<void> getDirectoryForLogRecord() async {
String currentDate = getCurrentDay();
if (currentDate != _currentDate) {
final String fileDir = await createDirectory();
file = File('${fileDir}/${currentDate}.log');
_sink = file!.openWrite(
mode: overrideExisting ? FileMode.writeOnly : FileMode.writeOnlyAppend,
encoding: encoding,
);
_currentDate = currentDate;
}
}
String getCurrentDay() {
String currentDate =
DateUtil.formatDate(DateTime.now(), format: "yyyyMMdd");
return currentDate;
}
void init() {
directoryLogRecord(onCallback: () {});
}
void directoryLogRecord({required Function onCallback}) {
getDirectoryForLogRecord().whenComplete(() {
onCallback();
});
}
void output(OutputEvent event) {
directoryLogRecord(onCallback: () {
if (_sink != null) {
if (Level.info == event.level ||
Level.warning == event.level ||
Level.error == event.level) {
_sink?.writeAll(event.lines, '\n');
}
}
});
}
void destroy() async {
await _sink?.flush();
await _sink?.close();
}
}
- 实现使用logger_manager
Future<String> createDirectory() async {
final Directory directory = await getApplicationDocumentsDirectory();
var file = Directory(directory.path+"/"+"lyd");
try {
bool exist = await file.exists();
if (exist == false) {
await file.create();
}
} catch(e) {
print("createDirectory error");
}
return file.path;
}
class LoggerManager {
//私有构造函数
LoggerManager._internal() {
deleteLogsOfBefore7Day();
initLogger();
}
//保存单例
static LoggerManager _singleton = LoggerManager._internal();
//工厂构造函数
factory LoggerManager() => _singleton;
late Logger logger;
// log初始化设置
Future<void> initLogger() async {
FileOutput fileOutPut = FileOutput();
ConsoleOutput consoleOutput = ConsoleOutput();
List<LogOutput> multiOutput = [fileOutPut, consoleOutput];
logger = Logger(
filter: DevelopmentFilter(),
// Use the default LogFilter (-> only log in debug mode)
// printer: SimplePrinter(
// colors: true,
// printTime: true,
// ),
printer: HybridPrinter(
PrettyPrinter(
noBoxingByDefault: false,
methodCount: 2,
// number of method calls to be displayed
errorMethodCount: 8,
// number of method calls if stacktrace is provided
lineLength: 120,
// width of the output
colors: true,
// Colorful log messages
printEmojis: false,
// Print an emoji for each log message
printTime: true, // Should each log print contain a timestamp
),
debug: SimplePrinter(),
),
// printer: PrefixPrinter(PrettyPrinter(
// noBoxingByDefault: true,
// methodCount: 2,
// // number of method calls to be displayed
// errorMethodCount: 8,
// // number of method calls if stacktrace is provided
// lineLength: 120,
// // width of the output
// colors: true,
// // Colorful log messages
// printEmojis: false,
// // Print an emoji for each log message
// printTime: true, // Should each log print contain a timestamp
// )),
// printer: PrettyPrinter(
// noBoxingByDefault: true,
// methodCount: 2,
// // number of method calls to be displayed
// errorMethodCount: 8,
// // number of method calls if stacktrace is provided
// lineLength: 120,
// // width of the output
// colors: true,
// // Colorful log messages
// printEmojis: false,
// // Print an emoji for each log message
// printTime: true, // Should each log print contain a timestamp
// ),
// Use the PrettyPrinter to format and print log
output: MultiOutput(
multiOutput,
), // Use the default LogOutput (-> send everything to console)
);
}
// Debug
void debug(String message) {
logger.d(message);
}
// verbose
void verbose(String message) {
logger.v(message);
}
// info
void info(String message) {
logger.i(message);
}
// warning
void warning(String message) {
logger.w(message);
}
// error
void error(String message) {
logger.e(message);
}
// 每次启动只保留7天内的日志,删除7天前的日志
Future<void> deleteLogsOfBefore7Day() async {
final String fileDir = await createDirectory();
// 获取目录的所有文件
var dir = Directory(fileDir);
Stream<FileSystemEntity> file = dir.list();
await for (FileSystemEntity x in file) {
// 获取文件的的名称
List<String> paths = x.path.split('/');
if (paths.isNotEmpty) {
String logName = paths.last.replaceAll('.log', '');
final logDate = DateUtil.getDateTime(logName);
final currentDate = DateTime.now();
//比较相差的天数
if (logDate != null) {
final difference = currentDate.difference(logDate!).inDays;
print("deleteLogsOfBefore7Day logDate:${logDate}, currentDate:${currentDate}, difference:${difference}");
if (difference > 7) {
var file = File(x.path);
// 删除文件
file.delete();
}
}
}
}
}
}
2.2 在main.dart初始化logger
// 配置logger
await LoggerManager().initLogger();
2.3 使用LoggerManager
logger的level定义
enum Level {
verbose,
debug,
info,
warning,
error,
wtf,
nothing,
}
可以在需要的地方使用LoggerManager
// verbose:
LoggerManager().verbose("App started at main.dart");
// debug:
LoggerManager().debug("App started at main.dart");
// info:
LoggerManager().info("App started at main.dart");
// warning:
LoggerManager().warning("App started at main.dart");
// error:
LoggerManager().error("App started at main.dart");
// wtf:
LoggerManager().wtf("App started at main.dart");
// nothing:
LoggerManager().nothing("App started at main.dart");
三、小结
flutter开发实战-日志logger写入文件及print,使用的是logger进行实现,输出日志logger的不同level:verbose、debug、info、warning、error、wtf、nothing。
学习记录,每天不停进步。