1 | // Copyright 2014 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | import 'dart:core'; |
6 | import 'dart:io'; |
7 | |
8 | /// Determines the level of logging. |
9 | /// |
10 | /// Verbosity is increasing from one (none) to five (fine). The sixth level |
11 | /// (all) logs everything. |
12 | enum LoggingLevel { |
13 | /// Logs no logs. |
14 | none, |
15 | |
16 | /// Logs severe messages at the most (severe messages are always logged). |
17 | /// |
18 | /// Severe means that the process has encountered a critical level of failure |
19 | /// in which it cannot recover and will terminate as a result. |
20 | severe, |
21 | |
22 | /// Logs warning messages at the most. |
23 | /// |
24 | /// Warning implies that an error was encountered, but the process will |
25 | /// attempt to continue, and may/may not succeed. |
26 | warning, |
27 | |
28 | /// Logs info messages at the most. |
29 | /// |
30 | /// An info message is for determining information about the state of the |
31 | /// application as it runs through execution. |
32 | info, |
33 | |
34 | /// Logs fine logs at the most. |
35 | /// |
36 | /// A fine message is one that is not important for logging outside of |
37 | /// debugging potential issues in the application. |
38 | fine, |
39 | |
40 | /// Logs everything. |
41 | all, |
42 | } |
43 | |
44 | /// Signature of a function that logs a [LogMessage]. |
45 | typedef LoggingFunction = void Function(LogMessage log); |
46 | |
47 | /// The default logging function. |
48 | /// |
49 | /// Runs the [print] function using the format string: |
50 | /// '[${log.levelName}]::${log.tag}--${log.time}: ${log.message}' |
51 | /// |
52 | /// Exits with status code 1 if the `log` is [LoggingLevel.severe]. |
53 | void defaultLoggingFunction(LogMessage log) { |
54 | // ignore: avoid_print |
55 | print('[ ${log.levelName}]:: ${log.tag}-- ${log.time}: ${log.message}' ); |
56 | if (log.level == LoggingLevel.severe) { |
57 | exit(1); |
58 | } |
59 | } |
60 | |
61 | /// Represents a logging message created by the logger. |
62 | /// |
63 | /// Includes a message, the time the message was created, the level of the log |
64 | /// as an enum, the name of the level as a string, and a tag. This class is used |
65 | /// to print from the global logging function defined in |
66 | /// [Logger.loggingFunction] (a function that can be user-defined). |
67 | class LogMessage { |
68 | /// Creates a log, including the level of the log, the time it was created, |
69 | /// and the actual log message. |
70 | /// |
71 | /// When this message is created, it sets its [time] to [DateTime.now]. |
72 | LogMessage(this.message, this.tag, this.level) |
73 | : levelName = level.toString().substring(level.toString().indexOf('.' ) + 1), |
74 | time = DateTime.now(); |
75 | |
76 | /// The actual log message. |
77 | final String message; |
78 | |
79 | /// The time the log message was created. |
80 | final DateTime time; |
81 | |
82 | /// The level of this log. |
83 | final LoggingLevel level; |
84 | |
85 | /// The human readable level of this log. |
86 | final String levelName; |
87 | |
88 | /// The tag associated with the message. This is set to [Logger.tag] when |
89 | /// emitted by a [Logger] object. |
90 | final String tag; |
91 | } |
92 | |
93 | /// Logs messages using the global [LoggingFunction] and logging level. |
94 | /// |
95 | /// Example of setting log level to [LoggingLevel.warning] and creating a |
96 | /// logging function: |
97 | /// |
98 | /// ```dart |
99 | /// Logger.globalLevel = LoggingLevel.warning; |
100 | /// ``` |
101 | class Logger { |
102 | /// Creates a logger with the given [tag]. |
103 | Logger(this.tag); |
104 | |
105 | /// The tag associated with the log message (usable in the logging function). |
106 | /// [LogMessage] objects emitted by this class will have [LogMessage.tag] set |
107 | /// to this value. |
108 | final String tag; |
109 | |
110 | /// Determines what to do when the [Logger] creates and attempts to log a |
111 | /// [LogMessage] object. |
112 | /// |
113 | /// This function can be reassigned to whatever functionality of your |
114 | /// choosing, so long as it has the same signature of [LoggingFunction] (it |
115 | /// can also be an asynchronous function, if doing file I/O, for |
116 | /// example). |
117 | static LoggingFunction loggingFunction = defaultLoggingFunction; |
118 | |
119 | /// Determines the logging level all [Logger] instances use. |
120 | static LoggingLevel globalLevel = LoggingLevel.none; |
121 | |
122 | /// Logs a [LoggingLevel.severe] level `message`. |
123 | /// |
124 | /// Severe messages are always logged, regardless of what level is set. |
125 | void severe(String message) { |
126 | loggingFunction(LogMessage(message, tag, LoggingLevel.severe)); |
127 | } |
128 | |
129 | /// Logs a [LoggingLevel.warning] level `message`. |
130 | void warning(String message) { |
131 | if (globalLevel.index >= LoggingLevel.warning.index) { |
132 | loggingFunction(LogMessage(message, tag, LoggingLevel.warning)); |
133 | } |
134 | } |
135 | |
136 | /// Logs a [LoggingLevel.info] level `message`. |
137 | void info(String message) { |
138 | if (globalLevel.index >= LoggingLevel.info.index) { |
139 | loggingFunction(LogMessage(message, tag, LoggingLevel.info)); |
140 | } |
141 | } |
142 | |
143 | /// Logs a [LoggingLevel.fine] level `message`. |
144 | void fine(String message) { |
145 | if (globalLevel.index >= LoggingLevel.fine.index) { |
146 | loggingFunction(LogMessage(message, tag, LoggingLevel.fine)); |
147 | } |
148 | } |
149 | } |
150 | |