@@ -129,6 +129,8 @@ use std::slice;
129
129
130
130
use sync:: one:: { Once , ONCE_INIT } ;
131
131
132
+ use directive:: LOG_LEVEL_NAMES ;
133
+
132
134
pub mod macros;
133
135
mod directive;
134
136
@@ -162,19 +164,42 @@ local_data_key!(local_logger: ~Logger:Send)
162
164
/// can have its own custom logger which can respond to logging messages
163
165
/// however it likes.
164
166
pub trait Logger {
165
- /// Logs a single message described by the `args` structure. The level is
166
- /// provided in case you want to do things like color the message, etc.
167
- fn log ( & mut self , level : u32 , args : & fmt:: Arguments ) ;
167
+ /// Logs a single message described by the `record`.
168
+ fn log ( & mut self , record : & LogRecord ) ;
168
169
}
169
170
170
171
struct DefaultLogger {
171
172
handle : LineBufferedWriter < io:: stdio:: StdWriter > ,
172
173
}
173
174
175
+ /// Wraps the log level with fmt implementations.
176
+ #[ deriving( Eq , Ord ) ]
177
+ pub struct LogLevel ( pub u32 ) ;
178
+
179
+ impl fmt:: Show for LogLevel {
180
+ fn fmt ( & self , fmt : & mut fmt:: Formatter ) -> fmt:: Result {
181
+ let LogLevel ( level) = * self ;
182
+ match LOG_LEVEL_NAMES . get ( level as uint - 1 ) {
183
+ Some ( name) => name. fmt ( fmt) ,
184
+ None => level. fmt ( fmt)
185
+ }
186
+ }
187
+ }
188
+
189
+ impl fmt:: Signed for LogLevel {
190
+ fn fmt ( & self , fmt : & mut fmt:: Formatter ) -> fmt:: Result {
191
+ let LogLevel ( level) = * self ;
192
+ write ! ( fmt. buf, "{}" , level)
193
+ }
194
+ }
195
+
174
196
impl Logger for DefaultLogger {
175
- // by default, just ignore the level
176
- fn log ( & mut self , _level : u32 , args : & fmt:: Arguments ) {
177
- match fmt:: writeln ( & mut self . handle , args) {
197
+ fn log ( & mut self , record : & LogRecord ) {
198
+ match write ! ( & mut self . handle,
199
+ "{}:{}: {}" ,
200
+ record. level,
201
+ record. module_path,
202
+ record. args) {
178
203
Err ( e) => fail ! ( "failed to log: {}" , e) ,
179
204
Ok ( ( ) ) => { }
180
205
}
@@ -198,14 +223,21 @@ impl Drop for DefaultLogger {
198
223
///
199
224
/// It is not recommended to call this function directly, rather it should be
200
225
/// invoked through the logging family of macros.
201
- pub fn log ( level : u32 , args : & fmt:: Arguments ) {
226
+ #[ doc( hidden) ]
227
+ pub fn log ( level : u32 , loc : & ' static LogLocation , args : & fmt:: Arguments ) {
202
228
// Completely remove the local logger from TLS in case anyone attempts to
203
229
// frob the slot while we're doing the logging. This will destroy any logger
204
230
// set during logging.
205
231
let mut logger = local_data:: pop ( local_logger) . unwrap_or_else ( || {
206
232
box DefaultLogger { handle : io:: stderr ( ) } as ~Logger : Send
207
233
} ) ;
208
- logger. log ( level, args) ;
234
+ logger. log ( & LogRecord {
235
+ level : LogLevel ( level) ,
236
+ args : args,
237
+ file : loc. file ,
238
+ module_path : loc. module_path ,
239
+ line : loc. line ,
240
+ } ) ;
209
241
local_data:: set ( local_logger, logger) ;
210
242
}
211
243
@@ -223,6 +255,34 @@ pub fn set_logger(logger: ~Logger:Send) -> Option<~Logger:Send> {
223
255
return prev;
224
256
}
225
257
258
+ /// A LogRecord is created by the logging macros, and passed as the only
259
+ /// argument to Loggers.
260
+ #[ deriving( Show ) ]
261
+ pub struct LogRecord < ' a > {
262
+
263
+ /// The module path of where the LogRecord originated.
264
+ pub module_path : & ' a str ,
265
+
266
+ /// The LogLevel of this record.
267
+ pub level : LogLevel ,
268
+
269
+ /// The arguments from the log line.
270
+ pub args : & ' a fmt:: Arguments < ' a > ,
271
+
272
+ /// The file of where the LogRecord originated.
273
+ pub file : & ' a str ,
274
+
275
+ /// The line number of where the LogRecord originated.
276
+ pub line : uint ,
277
+ }
278
+
279
+ #[ doc( hidden) ]
280
+ pub struct LogLocation {
281
+ pub module_path : & ' static str ,
282
+ pub file : & ' static str ,
283
+ pub line : uint ,
284
+ }
285
+
226
286
/// Tests whether a given module's name is enabled for a particular level of
227
287
/// logging. This is the second layer of defense about determining whether a
228
288
/// module's log statement should be emitted or not.
0 commit comments