@@ -8,9 +8,7 @@ import 'dart:ui';
8
8
import 'package:flutter/foundation.dart' ;
9
9
import 'package:path/path.dart' as p;
10
10
11
- class LogFileManager {
12
- LogFileManager ._(this ._sendPort);
13
-
11
+ abstract class LogFileManager {
14
12
static LogFileManager ? _instance;
15
13
16
14
static LogFileManager ? get instance => _instance ?? = _fromOtherIsolate ();
@@ -20,36 +18,63 @@ class LogFileManager {
20
18
static LogFileManager ? _fromOtherIsolate () {
21
19
final sendPort = IsolateNameServer .lookupPortByName (_logPortName);
22
20
if (sendPort == null ) {
21
+ debugPrint ('[mixin_logger] no logger isolate found' );
23
22
return null ;
24
23
}
25
- return LogFileManager ._ (sendPort);
24
+ return _LogFileMangerForOtherIsolate (sendPort);
26
25
}
27
26
28
27
static Future <void > init (
29
28
String logDir,
30
29
int maxFileCount,
31
- int maxFileLength,
32
- ) async {
30
+ int maxFileLength, {
31
+ String ? fileLeading,
32
+ }) async {
33
33
final receiver = ReceivePort ();
34
34
await Isolate .spawn (
35
35
_logIsolate,
36
- [receiver.sendPort, logDir, maxFileCount, maxFileLength],
36
+ [
37
+ receiver.sendPort,
38
+ logDir,
39
+ maxFileCount,
40
+ maxFileLength,
41
+ fileLeading,
42
+ ],
37
43
);
38
- final sendPort = await receiver.first as SendPort ;
39
- final removed = IsolateNameServer .removePortNameMapping (_logPortName);
40
- if (removed) {
41
- debugPrint ('Removed old logger isolate. this is ok if hot restarted app' );
42
- }
43
- IsolateNameServer .registerPortWithName (sendPort, _logPortName);
44
- }
44
+ final completer = Completer <void >();
45
+ receiver.listen ((message) {
46
+ if (message is SendPort ) {
47
+ final sendPort = message;
48
+ final removed = IsolateNameServer .removePortNameMapping (_logPortName);
49
+ if (removed) {
50
+ debugPrint (
51
+ 'Removed old logger isolate. this is ok if hot restarted app' );
52
+ }
53
+ IsolateNameServer .registerPortWithName (sendPort, _logPortName);
54
+ completer.complete ();
55
+ } else {
56
+ assert (false , 'unknown message: $message ' );
57
+ }
58
+ });
45
59
46
- final SendPort _sendPort;
60
+ return completer.future;
61
+ }
47
62
48
63
static Future <void > _logIsolate (List <dynamic > args) async {
49
64
final responsePort = args[0 ] as SendPort ;
50
65
final messageReceiver = ReceivePort ();
51
66
final dir = args[1 ] as String ;
52
- final logFileHandler = LogFileHandler (dir);
67
+ final maxFileCount = args[2 ] as int ;
68
+ final maxFileLength = args[3 ] as int ;
69
+ final fileLeading = args[4 ] as String ? ;
70
+
71
+ final logFileHandler = LogFileHandler (
72
+ dir,
73
+ maxFileCount: maxFileCount,
74
+ maxFileLength: maxFileLength,
75
+ fileLeading: fileLeading,
76
+ );
77
+ LogFileManager ._instance = _LogFileManagerForLogIsolate (logFileHandler);
53
78
messageReceiver.listen ((message) {
54
79
if (message is String ) {
55
80
logFileHandler.write (message);
@@ -58,11 +83,32 @@ class LogFileManager {
58
83
responsePort.send (messageReceiver.sendPort);
59
84
}
60
85
86
+ Future <void > write (String message);
87
+ }
88
+
89
+ class _LogFileMangerForOtherIsolate implements LogFileManager {
90
+ _LogFileMangerForOtherIsolate (this ._sendPort);
91
+
92
+ final SendPort _sendPort;
93
+
94
+ @override
61
95
Future <void > write (String message) async {
62
96
_sendPort.send (message);
63
97
}
64
98
}
65
99
100
+ class _LogFileManagerForLogIsolate implements LogFileManager {
101
+ _LogFileManagerForLogIsolate (this .handler);
102
+
103
+ final LogFileHandler handler;
104
+
105
+ @override
106
+ Future <void > write (String message) {
107
+ handler.write (message);
108
+ return Future .value ();
109
+ }
110
+ }
111
+
66
112
final _fileNameRegex = RegExp (r'^log_\d+.log$' );
67
113
final _fileNumberExtractRegex = RegExp (r'(?<=_)\d+(?=.log)' );
68
114
@@ -73,6 +119,7 @@ class LogFileHandler {
73
119
this .directory, {
74
120
this .maxFileCount = 10 ,
75
121
this .maxFileLength = 1024 * 1024 * 10 , // 10 MB
122
+ this .fileLeading,
76
123
}) : assert (maxFileCount >= 1 ),
77
124
assert (maxFileLength >= 0 ) {
78
125
final dir = Directory (directory);
@@ -108,10 +155,12 @@ class LogFileHandler {
108
155
109
156
void _prepareOutputFile () {
110
157
final File outputFile;
158
+ var newFileCreated = false ;
111
159
if (files.isEmpty) {
112
160
final file = File (p.join (directory, _generateFileName (0 )));
113
161
files[0 ] = file;
114
162
outputFile = file;
163
+ newFileCreated = true ;
115
164
} else {
116
165
final max = files.keys.reduce (math.max);
117
166
final file = files[max];
@@ -123,6 +172,7 @@ class LogFileHandler {
123
172
final file = File (p.join (directory, _generateFileName (nextIndex)));
124
173
files[nextIndex] = file;
125
174
outputFile = file;
175
+ newFileCreated = true ;
126
176
}
127
177
if (files.length > maxFileCount) {
128
178
final min = files.keys.reduce (math.min);
@@ -142,6 +192,10 @@ class LogFileHandler {
142
192
}
143
193
_logFile = outputFile;
144
194
_currentFileLength = outputFile.lengthSync ();
195
+ if (newFileCreated && fileLeading != null ) {
196
+ write (fileLeading! );
197
+ write ('\n ' );
198
+ }
145
199
}
146
200
147
201
final String directory;
@@ -155,6 +209,8 @@ class LogFileHandler {
155
209
156
210
final int maxFileLength;
157
211
212
+ final String ? fileLeading;
213
+
158
214
void write (String message) {
159
215
assert (_logFile != null , 'Log file is null' );
160
216
final bytes = utf8.encode ('$message \n ' );
0 commit comments