1 | | | import 'dart:developer' as dev show log; |
2 | | |
|
3 | | | import 'squadron.dart'; |
4 | | |
|
5 | | | /// Basic interface for logging |
6 | | | abstract class SquadronLogger { |
7 | | | /// Gets the log level |
8 | | | int get logLevel; |
9 | | |
|
10 | | | /// Sets the log level |
11 | | | set logLevel(int value); |
12 | | |
|
13 | | | /// Logs a message at [SquadronLogLevel.FINEST] level |
14 | | | void finest(dynamic message); |
15 | | |
|
16 | | | /// Logs a message at [SquadronLogLevel.FINER] level |
17 | | | void finer(dynamic message); |
18 | | |
|
19 | | | /// Logs a message at [SquadronLogLevel.FINE] level |
20 | | | void fine(dynamic message); |
21 | | |
|
22 | | | /// Logs a message at [SquadronLogLevel.CONFIG] level |
23 | | | void config(dynamic message); |
24 | | |
|
25 | | | /// Logs a message at [SquadronLogLevel.INFO] level |
26 | | | void info(dynamic message); |
27 | | |
|
28 | | | /// Logs a message at [SquadronLogLevel.WARNING] level |
29 | | | void warning(dynamic message); |
30 | | |
|
31 | | | /// Logs a message at [SquadronLogLevel.SEVERE] level |
32 | | | void severe(dynamic message); |
33 | | |
|
34 | | | /// Logs a message at [SquadronLogLevel.SHOUT] level |
35 | | | void shout(dynamic message); |
36 | | | } |
37 | | |
|
38 | | | /// Base class for simple loggers |
39 | | | abstract class BaseSquadronLogger implements SquadronLogger { |
40 | | | @override |
41 | | | int logLevel = SquadronLogLevel.SEVERE; |
42 | | |
|
43 | | | /// Base logging method. Implement this method to display the [message]. |
44 | | | /// The method is called if the log level is enabled and is provided with a formatted message such as `[timestamp] [log-level] [Squadron.id] text of the message` |
45 | | | void log(String message); |
46 | | |
|
47 | | 2 | void _log(int level, dynamic message) { |
48 | | 3 | if (level >= logLevel) { |
49 | | 2 | if (message is Function) { |
50 | | 2 | message = message(); |
51 | | | } |
52 | | | final header = |
53 | | 7 | '[${DateTime.now().toUtc().toIso8601String()}] [${SquadronLogLevel.getName(level)}] [${Squadron.id}]'; |
54 | | | Iterable<String> lines; |
55 | | 2 | if (message is Iterable) { |
56 | | 1 | lines = message |
57 | | 4 | .map((m) => m?.toString() ?? '') |
58 | | 5 | .expand((m) => m.toString().split('\n')) |
59 | | 4 | .where((m) => m.isNotEmpty); |
60 | | | } else { |
61 | | 6 | lines = message?.toString().split('\n').where((m) => m.isNotEmpty) ?? |
62 | | 0 | const []; |
63 | | | } |
64 | | 3 | for (var line in lines) { |
65 | | 2 | log('$header $line'); |
66 | | | } |
67 | | | } |
68 | | 1 | } |
69 | | |
|
70 | | 1 | @override |
71 | | 2 | void finest(dynamic message) => _log(SquadronLogLevel.FINEST, message); |
72 | | |
|
73 | | 1 | @override |
74 | | 2 | void finer(dynamic message) => _log(SquadronLogLevel.FINER, message); |
75 | | |
|
76 | | 1 | @override |
77 | | 2 | void fine(dynamic message) => _log(SquadronLogLevel.FINE, message); |
78 | | |
|
79 | | 1 | @override |
80 | | 2 | void config(dynamic message) => _log(SquadronLogLevel.CONFIG, message); |
81 | | |
|
82 | | 1 | @override |
83 | | 2 | void info(dynamic message) => _log(SquadronLogLevel.INFO, message); |
84 | | |
|
85 | | 1 | @override |
86 | | 2 | void warning(dynamic message) => _log(SquadronLogLevel.WARNING, message); |
87 | | |
|
88 | | 1 | @override |
89 | | 2 | void severe(dynamic message) => _log(SquadronLogLevel.SEVERE, message); |
90 | | |
|
91 | | 1 | @override |
92 | | 2 | void shout(dynamic message) => _log(SquadronLogLevel.SHOUT, message); |
93 | | | } |
94 | | |
|
95 | | | class DevSquadronLogger extends BaseSquadronLogger { |
96 | | 0 | @override |
97 | | |
|
98 | | | /// Log based on `dart:developer` |
99 | | 0 | void log(dynamic message) => dev.log(message?.toString() ?? ''); |
100 | | | } |
101 | | |
|
102 | | | class ConsoleSquadronLogger extends BaseSquadronLogger { |
103 | | | /// Log to console |
104 | | 0 | @override |
105 | | 0 | void log(dynamic message) => print(message); |
106 | | | } |
107 | | |
|
108 | | | /// Log level constants, compatible with `package:logging` |
109 | | | class SquadronLogLevel { |
110 | | 0 | SquadronLogLevel._(); |
111 | | |
|
112 | | | /// Lowest log level |
113 | | | // ignore: constant_identifier_names |
114 | | | static const ALL = 0; |
115 | | |
|
116 | | | /// Finest log level |
117 | | | // ignore: constant_identifier_names |
118 | | | static const FINEST = 300; |
119 | | |
|
120 | | | /// Finer log level |
121 | | | // ignore: constant_identifier_names |
122 | | | static const FINER = 400; |
123 | | |
|
124 | | | /// Fine log level |
125 | | | // ignore: constant_identifier_names |
126 | | | static const FINE = 500; |
127 | | |
|
128 | | | /// Config log level |
129 | | | // ignore: constant_identifier_names |
130 | | | static const CONFIG = 700; |
131 | | |
|
132 | | | /// Information log level |
133 | | | // ignore: constant_identifier_names |
134 | | | static const INFO = 800; |
135 | | |
|
136 | | | /// Warning log level |
137 | | | // ignore: constant_identifier_names |
138 | | | static const WARNING = 900; |
139 | | |
|
140 | | | /// Severe log level |
141 | | | // ignore: constant_identifier_names |
142 | | | static const SEVERE = 1000; |
143 | | |
|
144 | | | /// Shout log level |
145 | | | // ignore: constant_identifier_names |
146 | | | static const SHOUT = 1200; |
147 | | |
|
148 | | | /// No logging |
149 | | | // ignore: constant_identifier_names |
150 | | | static const OFF = 2000; |
151 | | |
|
152 | | | /// Gets the log level name |
153 | | 2 | static String getName(int logLevel) { |
154 | | 2 | if (logLevel < FINEST) return 'ALL'; |
155 | | 2 | if (logLevel < FINER) return 'FINEST'; |
156 | | 2 | if (logLevel < FINE) return 'FINER'; |
157 | | 2 | if (logLevel < CONFIG) return 'FINE'; |
158 | | 2 | if (logLevel < INFO) return 'CONFIG'; |
159 | | 2 | if (logLevel < WARNING) return 'INFO'; |
160 | | 2 | if (logLevel < SEVERE) return 'WARNING'; |
161 | | 2 | if (logLevel < SHOUT) return 'SEVERE'; |
162 | | 2 | if (logLevel < OFF) return 'SHOUT'; |
163 | | 0 | return 'OFF'; |
164 | | 1 | } |
165 | | | } |