Skip to content

Commit c891fa3

Browse files
committed
Fix #6031. Allow symbolic log levels, not just numbers.
1 parent 12bca20 commit c891fa3

File tree

2 files changed

+58
-21
lines changed

2 files changed

+58
-21
lines changed

doc/rust.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3385,9 +3385,11 @@ The path to a module consists of the crate name, any parent modules,
33853385
then the module itself, all separated by double colons (`::`). The
33863386
optional log level can be appended to the module path with an equals
33873387
sign (`=`) followed by the log level, from 1 to 4, inclusive. Level 1
3388-
is the error level, 2 is warning, 3 info, and 4 debug. Any logs
3389-
less than or equal to the specified level will be output. If not
3390-
specified then log level 4 is assumed.
3388+
is the error level, 2 is warning, 3 info, and 4 debug. You can also
3389+
use the symbolic constants `error`, `warn`, `info`, and `debug`. Any
3390+
logs less than or equal to the specified level will be output. If not
3391+
specified then log level 4 is assumed. However, debug messages are
3392+
only available if `--cfg=debug` is passed to `rustc`.
33913393

33923394
As an example, to see all the logs generated by the compiler, you would set
33933395
`RUST_LOG` to `rustc`, which is the crate name (as specified in its `link`

src/libstd/rt/logging.rs

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
use cast::transmute;
1111
use either::*;
1212
use libc::{c_void, uintptr_t, c_char, exit, STDERR_FILENO};
13-
use option::{Some, None};
13+
use option::{Some, None, Option};
1414
use rt::util::dumb_println;
1515
use str::StrSlice;
1616
use str::raw::from_c_str;
1717
use u32;
18+
use u32::{min};
1819
use unstable::raw::Closure;
1920
use vec::ImmutableVector;
2021

@@ -30,7 +31,6 @@ struct ModEntry{
3031
log_level: *mut u32
3132
}
3233

33-
static MAX_LOG_DIRECTIVES: u32 = 255;
3434
static MAX_LOG_LEVEL: u32 = 255;
3535
static DEFAULT_LOG_LEVEL: u32 = 1;
3636

@@ -68,42 +68,68 @@ fn iter_crate_map(map: *u8, f: &fn(*mut ModEntry)) {
6868
data: *c_void);
6969
}
7070
}
71+
static log_level_names : &'static[&'static str] = &'static["error", "warn", "info", "debug"];
72+
73+
/// Parse an individual log level that is either a number or a symbolic log level
74+
fn parse_log_level(level: &str) -> Option<u32> {
75+
let num = u32::from_str(level);
76+
let mut log_level;
77+
match (num) {
78+
Some(num) => {
79+
if num < MAX_LOG_LEVEL {
80+
log_level = Some(num);
81+
} else {
82+
log_level = Some(MAX_LOG_LEVEL);
83+
}
84+
}
85+
_ => {
86+
let position = log_level_names.iter().position(|&name| name == level);
87+
match (position) {
88+
Some(position) => {
89+
log_level = Some(min(MAX_LOG_LEVEL, (position + 1) as u32))
90+
},
91+
_ => {
92+
log_level = None;
93+
}
94+
}
95+
}
96+
}
97+
log_level
98+
}
99+
71100

72101
/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1")
73102
/// and return a vector with log directives.
74-
/// Valid log levels are 0-255, with the most likely ones being 0-3 (defined in std::).
103+
/// Valid log levels are 0-255, with the most likely ones being 1-4 (defined in std::).
104+
/// Also supports string log levels of error, warn, info, and debug
105+
75106
fn parse_logging_spec(spec: ~str) -> ~[LogDirective]{
76107
let mut dirs = ~[];
77108
for s in spec.split_iter(',') {
78109
let parts: ~[&str] = s.split_iter('=').collect();
79-
let mut loglevel;
110+
let mut log_level;
80111
match parts.len() {
81-
1 => loglevel = MAX_LOG_LEVEL,
112+
1 => log_level = MAX_LOG_LEVEL,
82113
2 => {
83-
let num = u32::from_str(parts[1]);
84-
match (num) {
114+
let possible_log_level = parse_log_level(parts[1]);
115+
match possible_log_level {
85116
Some(num) => {
86-
if num < MAX_LOG_LEVEL {
87-
loglevel = num;
88-
} else {
89-
loglevel = MAX_LOG_LEVEL;
90-
}
91-
}
117+
log_level = num;
118+
},
92119
_ => {
93-
dumb_println(fmt!("warning: invalid logging spec \
94-
'%s', ignoring it", s));
95-
loop;
120+
dumb_println(fmt!("warning: invalid logging spec \
121+
'%s', ignoring it", parts[1]));
122+
loop;
96123
}
97124
}
98-
if loglevel > MAX_LOG_LEVEL { loglevel = MAX_LOG_LEVEL}
99125
},
100126
_ => {
101127
dumb_println(fmt!("warning: invalid logging spec '%s',\
102128
ignoring it", s));
103129
loop;
104130
}
105131
}
106-
let dir = LogDirective {name: parts[0].to_owned(), level: loglevel};
132+
let dir = LogDirective {name: parts[0].to_owned(), level: log_level};
107133
dirs.push(dir);
108134
}
109135
return dirs;
@@ -268,6 +294,15 @@ fn parse_logging_spec_invalid_log_level() {
268294
assert_eq!(dirs[0].level, 4);
269295
}
270296
297+
#[test]
298+
fn parse_logging_spec_string_log_level() {
299+
// test parse_logging_spec with 'warn' as log level
300+
let dirs: ~[LogDirective] = parse_logging_spec(~"crate1::mod1=wrong,crate2=warn");
301+
assert_eq!(dirs.len(), 1);
302+
assert!(dirs[0].name == ~"crate2");
303+
assert_eq!(dirs[0].level, 2);
304+
}
305+
271306
// Tests for update_entry
272307
#[test]
273308
fn update_entry_match_full_path() {

0 commit comments

Comments
 (0)