mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 06:51:58 +00:00
Refactor the logging system for fewer allocations
This lifts various restrictions on the runtime, for example the character limit when logging a message. Right now the old debug!-style macros still involve allocating (because they use fmt! syntax), but the new debug2! macros don't involve allocating at all (unless the formatter for a type requires allocation.
This commit is contained in:
parent
af25f58ac3
commit
eb2b25dd6d
@ -10,11 +10,11 @@
|
||||
|
||||
//! Logging
|
||||
|
||||
use fmt;
|
||||
use option::*;
|
||||
use os;
|
||||
use rt;
|
||||
use rt::logging::{Logger, StdErrLogger};
|
||||
use send_str::SendStrOwned;
|
||||
|
||||
/// Turns on logging to stdout globally
|
||||
pub fn console_on() {
|
||||
@ -37,7 +37,17 @@ pub fn console_off() {
|
||||
rt::logging::console_off();
|
||||
}
|
||||
|
||||
fn newsched_log_str(msg: ~str) {
|
||||
#[cfg(stage0)]
|
||||
#[doc(hidden)]
|
||||
pub fn log(_level: u32, s: ~str) {
|
||||
// this is a terrible approximation, but it gets the job done (for stage0 at
|
||||
// least)
|
||||
::io::println(s);
|
||||
}
|
||||
|
||||
#[allow(missing_doc)]
|
||||
#[cfg(not(stage0))]
|
||||
pub fn log(_level: u32, args: &fmt::Arguments) {
|
||||
use rt::task::Task;
|
||||
use rt::local::Local;
|
||||
|
||||
@ -46,20 +56,13 @@ fn newsched_log_str(msg: ~str) {
|
||||
match optional_task {
|
||||
Some(local) => {
|
||||
// Use the available logger
|
||||
(*local).logger.log(SendStrOwned(msg));
|
||||
(*local).logger.log(args);
|
||||
}
|
||||
None => {
|
||||
// There is no logger anywhere, just write to stderr
|
||||
let mut logger = StdErrLogger;
|
||||
logger.log(SendStrOwned(msg));
|
||||
logger.log(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: This will change soon to not require an allocation. This is an unstable
|
||||
// api which should not be used outside of the macros in ext/expand.
|
||||
#[doc(hidden)]
|
||||
pub fn log(_level: u32, msg: ~str) {
|
||||
newsched_log_str(msg);
|
||||
}
|
||||
|
@ -7,9 +7,12 @@
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use fmt;
|
||||
use from_str::from_str;
|
||||
use libc::{uintptr_t, exit, STDERR_FILENO};
|
||||
use libc::{uintptr_t, exit};
|
||||
use option::{Some, None, Option};
|
||||
use rt;
|
||||
use rt::util::dumb_println;
|
||||
use rt::crate_map::{ModEntry, iter_crate_map};
|
||||
use rt::crate_map::get_crate_map;
|
||||
@ -18,7 +21,6 @@ use str::raw::from_c_str;
|
||||
use u32;
|
||||
use vec::ImmutableVector;
|
||||
use cast::transmute;
|
||||
use send_str::{SendStr, SendStrOwned, SendStrStatic};
|
||||
|
||||
struct LogDirective {
|
||||
name: Option<~str>,
|
||||
@ -171,44 +173,33 @@ fn update_log_settings(crate_map: *u8, settings: ~str) {
|
||||
}
|
||||
|
||||
pub trait Logger {
|
||||
fn log(&mut self, msg: SendStr);
|
||||
fn log(&mut self, args: &fmt::Arguments);
|
||||
}
|
||||
|
||||
pub struct StdErrLogger;
|
||||
|
||||
impl Logger for StdErrLogger {
|
||||
fn log(&mut self, msg: SendStr) {
|
||||
use io::{Writer, WriterUtil};
|
||||
|
||||
if !should_log_console() {
|
||||
return;
|
||||
}
|
||||
|
||||
let s: &str = match msg {
|
||||
SendStrOwned(ref s) => {
|
||||
let slc: &str = *s;
|
||||
slc
|
||||
},
|
||||
SendStrStatic(s) => s,
|
||||
};
|
||||
|
||||
// Truncate the string
|
||||
let buf_bytes = 2048;
|
||||
if s.len() > buf_bytes {
|
||||
let s = s.slice(0, buf_bytes) + "[...]";
|
||||
print(s);
|
||||
} else {
|
||||
print(s)
|
||||
};
|
||||
|
||||
fn print(s: &str) {
|
||||
let dbg = STDERR_FILENO as ::io::fd_t;
|
||||
dbg.write_str(s);
|
||||
dbg.write_str("\n");
|
||||
dbg.flush();
|
||||
fn log(&mut self, args: &fmt::Arguments) {
|
||||
if should_log_console() {
|
||||
fmt::write(self as &mut rt::io::Writer, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl rt::io::Writer for StdErrLogger {
|
||||
fn write(&mut self, buf: &[u8]) {
|
||||
// Nothing like swapping between I/O implementations! In theory this
|
||||
// could use the libuv bindings for writing to file descriptors, but
|
||||
// that may not necessarily be desirable because logging should work
|
||||
// outside of the uv loop. (modify with caution)
|
||||
use io::Writer;
|
||||
let dbg = ::libc::STDERR_FILENO as ::io::fd_t;
|
||||
dbg.write(buf);
|
||||
}
|
||||
|
||||
fn flush(&mut self) {}
|
||||
}
|
||||
|
||||
/// Configure logging by traversing the crate map and setting the
|
||||
/// per-module global logging flags based on the logging spec
|
||||
pub fn init() {
|
||||
|
@ -224,4 +224,5 @@ mod std {
|
||||
pub use os;
|
||||
pub use fmt;
|
||||
pub use to_bytes;
|
||||
pub use logging;
|
||||
}
|
||||
|
@ -125,14 +125,41 @@ impl FailWithCause for &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME #4427: Temporary until rt::rt_fail_ goes away
|
||||
// This stage0 version is incredibly wrong.
|
||||
#[cfg(stage0)]
|
||||
pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
|
||||
use option::{Some, None};
|
||||
use rt::in_green_task_context;
|
||||
use rt::task::Task;
|
||||
use rt::local::Local;
|
||||
use rt::logging::Logger;
|
||||
use send_str::SendStrOwned;
|
||||
use str::Str;
|
||||
|
||||
unsafe {
|
||||
let msg = str::raw::from_c_str(msg);
|
||||
let file = str::raw::from_c_str(file);
|
||||
if in_green_task_context() {
|
||||
rterrln!("task failed at '%s', %s:%i", msg, file, line as int);
|
||||
} else {
|
||||
rterrln!("failed in non-task context at '%s', %s:%i",
|
||||
msg, file, line as int);
|
||||
}
|
||||
|
||||
let task: *mut Task = Local::unsafe_borrow();
|
||||
if (*task).unwinder.unwinding {
|
||||
rtabort!("unwinding again");
|
||||
}
|
||||
(*task).unwinder.begin_unwind();
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME #4427: Temporary until rt::rt_fail_ goes away
|
||||
#[cfg(not(stage0))]
|
||||
pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
|
||||
use rt::in_green_task_context;
|
||||
use rt::task::Task;
|
||||
use rt::local::Local;
|
||||
use rt::logging::Logger;
|
||||
use str::Str;
|
||||
|
||||
unsafe {
|
||||
@ -140,22 +167,14 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
|
||||
let msg = str::raw::from_c_str(msg);
|
||||
let file = str::raw::from_c_str(file);
|
||||
|
||||
// XXX: Logging doesn't work correctly in non-task context because it
|
||||
// invokes the local heap
|
||||
if in_green_task_context() {
|
||||
// XXX: Logging doesn't work here - the check to call the log
|
||||
// function never passes - so calling the log function directly.
|
||||
// Be careful not to allocate in this block, if we're failing we may
|
||||
// have been failing due to a lack of memory in the first place...
|
||||
do Local::borrow |task: &mut Task| {
|
||||
let msg = match task.name {
|
||||
Some(ref name) =>
|
||||
fmt!("task '%s' failed at '%s', %s:%i",
|
||||
name.as_slice(), msg, file, line as int),
|
||||
None =>
|
||||
fmt!("task <unnamed> failed at '%s', %s:%i",
|
||||
msg, file, line as int)
|
||||
};
|
||||
|
||||
task.logger.log(SendStrOwned(msg));
|
||||
let n = task.name.map(|n| n.as_slice()).unwrap_or("<unnamed>");
|
||||
format_args!(|args| { task.logger.log(args) },
|
||||
"task '{}' failed at '{}', {}:{}",
|
||||
n, msg.as_slice(), file.as_slice(), line);
|
||||
}
|
||||
} else {
|
||||
rterrln!("failed in non-task context at '%s', %s:%i",
|
||||
|
@ -813,13 +813,17 @@ pub fn std_macros() -> @str {
|
||||
($lvl:expr, $arg:expr) => ({
|
||||
let lvl = $lvl;
|
||||
if lvl <= __log_level() {
|
||||
::std::logging::log(lvl, fmt!(\"%?\", $arg))
|
||||
format_args!(|args| {
|
||||
::std::logging::log(lvl, args)
|
||||
}, \"{}\", fmt!(\"%?\", $arg))
|
||||
}
|
||||
});
|
||||
($lvl:expr, $($arg:expr),+) => ({
|
||||
let lvl = $lvl;
|
||||
if lvl <= __log_level() {
|
||||
::std::logging::log(lvl, fmt!($($arg),+))
|
||||
format_args!(|args| {
|
||||
::std::logging::log(lvl, args)
|
||||
}, \"{}\", fmt!($($arg),+))
|
||||
}
|
||||
})
|
||||
)
|
||||
@ -834,7 +838,9 @@ pub fn std_macros() -> @str {
|
||||
($lvl:expr, $($arg:tt)+) => ({
|
||||
let lvl = $lvl;
|
||||
if lvl <= __log_level() {
|
||||
::std::logging::log(lvl, format!($($arg)+))
|
||||
format_args!(|args| {
|
||||
::std::logging::log(lvl, args)
|
||||
}, $($arg)+)
|
||||
}
|
||||
})
|
||||
)
|
||||
|
@ -20,6 +20,5 @@ impl Drop for C {
|
||||
|
||||
fn main() {
|
||||
let c = C{ x: 2};
|
||||
let d = c.clone(); //~ ERROR does not implement any method in scope
|
||||
error!("%?", d.x);
|
||||
let _d = c.clone(); //~ ERROR does not implement any method in scope
|
||||
}
|
||||
|
@ -1,74 +0,0 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that logs add `[...]` to truncated lines
|
||||
// error-pattern:[...]
|
||||
|
||||
fn main() {
|
||||
fail!("\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
|
||||
");
|
||||
}
|
Loading…
Reference in New Issue
Block a user