-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathlogger_manager.dart
More file actions
220 lines (181 loc) · 6.55 KB
/
logger_manager.dart
File metadata and controls
220 lines (181 loc) · 6.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
import 'dart:io';
import 'package:alice/alice.dart';
import 'package:app/access/logger/alice_output.dart';
import 'package:app/access/logger/logger_repository.dart';
import 'package:app/access/logger/custom_console_output.dart';
import 'package:app/access/logger/custom_file_output.dart';
import 'package:app/business/logger/level_log_filter.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:logger/logger.dart';
import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';
/// Service that manages everything related to logging.
abstract interface class LoggerManager {
factory LoggerManager({
required LoggerRepository loggerRepository,
required Alice alice,
}) = _LoggerManager;
/// Gets whether console logging is enabled.
bool get isConsoleLoggingEnabled;
/// Gets whether file logging is enabled.
bool get isFileLoggingEnabled;
/// Gets whether logging configuration has been changed via either [setIsConsoleLoggingEnabled] or [setIsFileLoggingEnabled].
bool get hasConfigurationBeenChanged;
/// Create an instance of [Logger].
Future<Logger> createLogInstance();
/// Deletes log file
/// The [bool] returned indicates whether the log file has been deleted successfully.
Future<bool> deleteLogFile();
/// Shares log file via email.
/// The [bool] returned indicates whether the file has been shared successfully (Dismissed by the user also counts as a success).
Future<bool> shareLogFile();
/// Sets whether console logging should be enabled on next app launch.
Future setIsConsoleLoggingEnabled(bool isConsoleLoggingEnabled);
/// Sets whether file logging should be enabled on next app launch.
Future setIsFileLoggingEnabled(bool isFileLoggingEnabled);
}
/// Implementation of [LoggerManager].
final class _LoggerManager implements LoggerManager {
final LoggerRepository _loggerRepository;
final Alice _alice;
late Logger _logger;
File? _logFile;
final String _fileName = "ApplicationTemplate.log";
late bool _initialIsConsoleLoggingEnabled;
late bool _initialIsFileLoggingEnabled;
@override
late bool isConsoleLoggingEnabled;
@override
late bool isFileLoggingEnabled;
@override
bool hasConfigurationBeenChanged = false;
_LoggerManager({
required LoggerRepository loggerRepository,
required Alice alice,
}) : _loggerRepository = loggerRepository,
_alice = alice;
@override
Future<Logger> createLogInstance() async {
final List<LogOutput> loggerOutputs = [];
final loggingConfiguration =
await _loggerRepository.getLoggingConfiguration();
_initialIsConsoleLoggingEnabled =
loggingConfiguration.isConsoleLoggingEnabled ??
bool.parse(dotenv.env["IS_CONSOLE_LOGGING_ENABLED"] ?? 'false');
if (_initialIsConsoleLoggingEnabled) {
loggerOutputs.add(CustomConsoleOutput());
loggerOutputs.add(AliceOutput(alice: _alice));
}
isConsoleLoggingEnabled = _initialIsConsoleLoggingEnabled;
_initialIsFileLoggingEnabled = loggingConfiguration.isFileLoggingEnabled ??
bool.parse(dotenv.env["IS_FILE_LOGGING_ENABLED"] ?? 'false');
if (_initialIsFileLoggingEnabled) {
// Initialize the log file.
final Directory appDocumentsDir =
await getApplicationDocumentsDirectory();
_logFile = File('${appDocumentsDir.path}/$_fileName');
loggerOutputs.add(CustomFileOutput(file: _logFile!));
}
isFileLoggingEnabled = _initialIsFileLoggingEnabled;
var minimumLevel = dotenv.env['MINIMUM_LEVEL']!.toLogLevel();
return _logger = Logger(
filter: LevelLogFilter(minimumLevel),
printer: PrefixPrinter(
PrettyPrinter(
methodCount: 0,
errorMethodCount: 9,
stackTraceBeginIndex: 1,
printTime: true,
printEmojis: false,
noBoxingByDefault: true,
),
),
output: MultiOutput(loggerOutputs),
);
}
@override
Future<bool> deleteLogFile() async {
_logger.d("Start deleting the log file.");
if (_logFile != null && await _logFile!.exists()) {
try {
_logger.t("Log file exists. It's time to delete it.");
await _logFile!.delete();
_logger.i("The log file was deleted successfully.");
return true;
} catch (e, stackTrace) {
_logger.e(
'Failed to delete the log file.',
error: e,
stackTrace: stackTrace,
);
}
}
_logger.w('No log file to delete.');
return false;
}
@override
Future<bool> shareLogFile() async {
_logger.d("Start sharing the log file.");
if (_logFile != null &&
(await _logFile!.exists()) &&
(await _logFile!.length()) > 0) {
try {
_logger.t("Log file exists. It's time to share it.");
var result = await Share.shareXFiles(
[XFile(_logFile!.path)],
subject: "Diagnostics - ApplicationTemplate ${DateTime.now()}",
);
_logger.i(
"Share execution has been successful. It returned the following status ${result.status}.");
return result.status != ShareResultStatus.unavailable;
} catch (e, stackTrace) {
_logger.e(
'Failed to share log file.',
error: e,
stackTrace: stackTrace,
);
}
}
_logger.w("There's no log file to share.");
return false;
}
@override
Future setIsConsoleLoggingEnabled(bool isConsoleLoggingEnabled) async {
await _loggerRepository.setIsConsoleLoggingEnabled(isConsoleLoggingEnabled);
this.isConsoleLoggingEnabled = isConsoleLoggingEnabled;
hasConfigurationBeenChanged = _checkIfChangesHaveBeenMade();
}
@override
Future setIsFileLoggingEnabled(bool isFileLoggingEnabled) async {
await _loggerRepository.setIsFileLoggingEnabled(isFileLoggingEnabled);
this.isFileLoggingEnabled = isFileLoggingEnabled;
hasConfigurationBeenChanged = _checkIfChangesHaveBeenMade();
}
bool _checkIfChangesHaveBeenMade() =>
isConsoleLoggingEnabled != _initialIsConsoleLoggingEnabled ||
isFileLoggingEnabled != _initialIsFileLoggingEnabled;
}
extension StringToLogLevel on String {
Level toLogLevel() {
switch (this) {
case 'all':
return Level.all;
case 'trace':
return Level.trace;
case 'debug':
return Level.debug;
case 'info':
return Level.info;
case 'warning':
return Level.warning;
case 'error':
return Level.error;
case 'fatal':
return Level.fatal;
case 'off':
return Level.off;
default:
return Level.debug;
}
}
}