@@ -129,6 +129,8 @@ use std::slice;
129129
130130use sync:: one:: { Once , ONCE_INIT } ;
131131
132+ use directive:: LOG_LEVEL_NAMES ;
133+
132134pub mod macros;
133135mod directive;
134136
@@ -162,19 +164,42 @@ local_data_key!(local_logger: ~Logger:Send)
162164/// can have its own custom logger which can respond to logging messages
163165/// however it likes.
164166pub 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 ) ;
168169}
169170
170171struct DefaultLogger {
171172 handle : LineBufferedWriter < io:: stdio:: StdWriter > ,
172173}
173174
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+
174196impl 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) {
178203 Err ( e) => fail ! ( "failed to log: {}" , e) ,
179204 Ok ( ( ) ) => { }
180205 }
@@ -198,14 +223,21 @@ impl Drop for DefaultLogger {
198223///
199224/// It is not recommended to call this function directly, rather it should be
200225/// 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 ) {
202228 // Completely remove the local logger from TLS in case anyone attempts to
203229 // frob the slot while we're doing the logging. This will destroy any logger
204230 // set during logging.
205231 let mut logger = local_data:: pop ( local_logger) . unwrap_or_else ( || {
206232 box DefaultLogger { handle : io:: stderr ( ) } as ~Logger : Send
207233 } ) ;
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+ } ) ;
209241 local_data:: set ( local_logger, logger) ;
210242}
211243
@@ -223,6 +255,34 @@ pub fn set_logger(logger: ~Logger:Send) -> Option<~Logger:Send> {
223255 return prev;
224256}
225257
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+
226286/// Tests whether a given module's name is enabled for a particular level of
227287/// logging. This is the second layer of defense about determining whether a
228288/// module's log statement should be emitted or not.
0 commit comments