Skip to content

Commit c684df1

Browse files
committed
Handle global log levels (fixes #6033)
1 parent c891fa3 commit c684df1

File tree

1 file changed

+100
-36
lines changed

1 file changed

+100
-36
lines changed

src/libstd/rt/logging.rs

Lines changed: 100 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,12 @@ use rt::util::dumb_println;
1515
use str::StrSlice;
1616
use str::raw::from_c_str;
1717
use u32;
18-
use u32::{min};
1918
use unstable::raw::Closure;
2019
use vec::ImmutableVector;
2120

2221

2322
struct LogDirective {
24-
name: ~str,
23+
name: Option<~str>,
2524
level: u32
2625
}
2726

@@ -74,7 +73,7 @@ static log_level_names : &'static[&'static str] = &'static["error", "warn", "inf
7473
fn parse_log_level(level: &str) -> Option<u32> {
7574
let num = u32::from_str(level);
7675
let mut log_level;
77-
match (num) {
76+
match num {
7877
Some(num) => {
7978
if num < MAX_LOG_LEVEL {
8079
log_level = Some(num);
@@ -84,9 +83,9 @@ fn parse_log_level(level: &str) -> Option<u32> {
8483
}
8584
_ => {
8685
let position = log_level_names.iter().position(|&name| name == level);
87-
match (position) {
86+
match position {
8887
Some(position) => {
89-
log_level = Some(min(MAX_LOG_LEVEL, (position + 1) as u32))
88+
log_level = Some(u32::min(MAX_LOG_LEVEL, (position + 1) as u32))
9089
},
9190
_ => {
9291
log_level = None;
@@ -108,8 +107,22 @@ fn parse_logging_spec(spec: ~str) -> ~[LogDirective]{
108107
for s in spec.split_iter(',') {
109108
let parts: ~[&str] = s.split_iter('=').collect();
110109
let mut log_level;
110+
let mut name = Some(parts[0].to_owned());
111111
match parts.len() {
112-
1 => log_level = MAX_LOG_LEVEL,
112+
1 => {
113+
//if the single argument is a log-level string or number,
114+
//treat that as a global fallback
115+
let possible_log_level = parse_log_level(parts[0]);
116+
match possible_log_level {
117+
Some(num) => {
118+
name = None;
119+
log_level = num;
120+
},
121+
_ => {
122+
log_level = MAX_LOG_LEVEL
123+
}
124+
}
125+
}
113126
2 => {
114127
let possible_log_level = parse_log_level(parts[1]);
115128
match possible_log_level {
@@ -129,7 +142,7 @@ fn parse_logging_spec(spec: ~str) -> ~[LogDirective]{
129142
loop;
130143
}
131144
}
132-
let dir = LogDirective {name: parts[0].to_owned(), level: log_level};
145+
let dir = LogDirective {name: name, level: log_level};
133146
dirs.push(dir);
134147
}
135148
return dirs;
@@ -139,18 +152,30 @@ fn parse_logging_spec(spec: ~str) -> ~[LogDirective]{
139152
/// of log directives
140153
fn update_entry(dirs: &[LogDirective], entry: *mut ModEntry) -> u32 {
141154
let mut new_lvl: u32 = DEFAULT_LOG_LEVEL;
142-
let mut longest_match = 0;
155+
let mut longest_match = -1i;
143156
unsafe {
144157
for dir in dirs.iter() {
145-
let name = from_c_str((*entry).name);
146-
if name.starts_with(dir.name) && dir.name.len() > longest_match {
147-
longest_match = dir.name.len();
148-
new_lvl = dir.level;
149-
}
158+
match dir.name {
159+
None => {
160+
if longest_match == -1 {
161+
longest_match = 0;
162+
new_lvl = dir.level;
163+
}
164+
}
165+
Some(ref dir_name) => {
166+
let name = from_c_str((*entry).name);
167+
let len = dir_name.len() as int;
168+
if name.starts_with(*dir_name) &&
169+
len >= longest_match {
170+
longest_match = len;
171+
new_lvl = dir.level;
172+
}
173+
}
174+
};
150175
}
151176
*(*entry).log_level = new_lvl;
152177
}
153-
if longest_match > 0 { return 1; } else { return 0; }
178+
if longest_match >= 0 { return 1; } else { return 0; }
154179
}
155180

156181
#[fixed_stack_segment] #[inline(never)]
@@ -264,54 +289,66 @@ extern {
264289
// Tests for parse_logging_spec()
265290
#[test]
266291
fn parse_logging_spec_valid() {
267-
let dirs: ~[LogDirective] = parse_logging_spec(~"crate1::mod1=1,crate1::mod2,crate2=4");
292+
let dirs = parse_logging_spec(~"crate1::mod1=1,crate1::mod2,crate2=4");
268293
assert_eq!(dirs.len(), 3);
269-
assert!(dirs[0].name == ~"crate1::mod1");
294+
assert!(dirs[0].name == Some(~"crate1::mod1"));
270295
assert_eq!(dirs[0].level, 1);
271296
272-
assert!(dirs[1].name == ~"crate1::mod2");
297+
assert!(dirs[1].name == Some(~"crate1::mod2"));
273298
assert_eq!(dirs[1].level, MAX_LOG_LEVEL);
274299
275-
assert!(dirs[2].name == ~"crate2");
300+
assert!(dirs[2].name == Some(~"crate2"));
276301
assert_eq!(dirs[2].level, 4);
277302
}
278303
279304
#[test]
280305
fn parse_logging_spec_invalid_crate() {
281306
// test parse_logging_spec with multiple = in specification
282-
let dirs: ~[LogDirective] = parse_logging_spec(~"crate1::mod1=1=2,crate2=4");
307+
let dirs = parse_logging_spec(~"crate1::mod1=1=2,crate2=4");
283308
assert_eq!(dirs.len(), 1);
284-
assert!(dirs[0].name == ~"crate2");
309+
assert!(dirs[0].name == Some(~"crate2"));
285310
assert_eq!(dirs[0].level, 4);
286311
}
287312
288313
#[test]
289314
fn parse_logging_spec_invalid_log_level() {
290315
// test parse_logging_spec with 'noNumber' as log level
291-
let dirs: ~[LogDirective] = parse_logging_spec(~"crate1::mod1=noNumber,crate2=4");
316+
let dirs = parse_logging_spec(~"crate1::mod1=noNumber,crate2=4");
292317
assert_eq!(dirs.len(), 1);
293-
assert!(dirs[0].name == ~"crate2");
318+
assert!(dirs[0].name == Some(~"crate2"));
294319
assert_eq!(dirs[0].level, 4);
295320
}
296321
297322
#[test]
298323
fn parse_logging_spec_string_log_level() {
299324
// test parse_logging_spec with 'warn' as log level
300-
let dirs: ~[LogDirective] = parse_logging_spec(~"crate1::mod1=wrong,crate2=warn");
325+
let dirs = parse_logging_spec(~"crate1::mod1=wrong,crate2=warn");
301326
assert_eq!(dirs.len(), 1);
302-
assert!(dirs[0].name == ~"crate2");
327+
assert!(dirs[0].name == Some(~"crate2"));
303328
assert_eq!(dirs[0].level, 2);
304329
}
305330
331+
#[test]
332+
fn parse_logging_spec_global() {
333+
// test parse_logging_spec with no crate
334+
let dirs = parse_logging_spec(~"warn,crate2=4");
335+
assert_eq!(dirs.len(), 2);
336+
assert!(dirs[0].name == None);
337+
assert_eq!(dirs[0].level, 2);
338+
assert!(dirs[1].name == Some(~"crate2"));
339+
assert_eq!(dirs[1].level, 4);
340+
}
341+
306342
// Tests for update_entry
307343
#[test]
308344
fn update_entry_match_full_path() {
309345
use c_str::ToCStr;
310-
let dirs = ~[LogDirective {name: ~"crate1::mod1", level: 2 },
311-
LogDirective {name: ~"crate2", level: 3}];
346+
let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
347+
LogDirective {name: Some(~"crate2"), level: 3}];
348+
let level = &mut 0;
312349
unsafe {
313350
do "crate1::mod1".to_c_str().with_ref |ptr| {
314-
let entry= &ModEntry {name: ptr, log_level: &mut 0};
351+
let entry= &ModEntry {name: ptr, log_level: level};
315352
let m = update_entry(dirs, transmute(entry));
316353
assert!(*entry.log_level == 2);
317354
assert!(m == 1);
@@ -322,11 +359,12 @@ fn update_entry_match_full_path() {
322359
#[test]
323360
fn update_entry_no_match() {
324361
use c_str::ToCStr;
325-
let dirs = ~[LogDirective {name: ~"crate1::mod1", level: 2 },
326-
LogDirective {name: ~"crate2", level: 3}];
362+
let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
363+
LogDirective {name: Some(~"crate2"), level: 3}];
364+
let level = &mut 0;
327365
unsafe {
328366
do "crate3::mod1".to_c_str().with_ref |ptr| {
329-
let entry= &ModEntry {name: ptr, log_level: &mut 0};
367+
let entry= &ModEntry {name: ptr, log_level: level};
330368
let m = update_entry(dirs, transmute(entry));
331369
assert!(*entry.log_level == DEFAULT_LOG_LEVEL);
332370
assert!(m == 0);
@@ -337,11 +375,12 @@ fn update_entry_no_match() {
337375
#[test]
338376
fn update_entry_match_beginning() {
339377
use c_str::ToCStr;
340-
let dirs = ~[LogDirective {name: ~"crate1::mod1", level: 2 },
341-
LogDirective {name: ~"crate2", level: 3}];
378+
let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
379+
LogDirective {name: Some(~"crate2"), level: 3}];
380+
let level = &mut 0;
342381
unsafe {
343382
do "crate2::mod1".to_c_str().with_ref |ptr| {
344-
let entry= &ModEntry {name: ptr, log_level: &mut 0};
383+
let entry= &ModEntry {name: ptr, log_level: level};
345384
let m = update_entry(dirs, transmute(entry));
346385
assert!(*entry.log_level == 3);
347386
assert!(m == 1);
@@ -352,14 +391,39 @@ fn update_entry_match_beginning() {
352391
#[test]
353392
fn update_entry_match_beginning_longest_match() {
354393
use c_str::ToCStr;
355-
let dirs = ~[LogDirective {name: ~"crate1::mod1", level: 2 },
356-
LogDirective {name: ~"crate2", level: 3}, LogDirective {name: ~"crate2::mod", level: 4}];
394+
let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
395+
LogDirective {name: Some(~"crate2"), level: 3},
396+
LogDirective {name: Some(~"crate2::mod"), level: 4}];
397+
let level = &mut 0;
357398
unsafe {
358399
do "crate2::mod1".to_c_str().with_ref |ptr| {
359-
let entry = &ModEntry {name: ptr, log_level: &mut 0};
400+
let entry = &ModEntry {name: ptr, log_level: level};
360401
let m = update_entry(dirs, transmute(entry));
361402
assert!(*entry.log_level == 4);
362403
assert!(m == 1);
363404
}
364405
}
365406
}
407+
408+
#[test]
409+
fn update_entry_match_default() {
410+
use c_str::ToCStr;
411+
let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
412+
LogDirective {name: None, level: 3}
413+
];
414+
let level = &mut 0;
415+
unsafe {
416+
do "crate1::mod1".to_c_str().with_ref |ptr| {
417+
let entry= &ModEntry {name: ptr, log_level: level};
418+
let m = update_entry(dirs, transmute(entry));
419+
assert!(*entry.log_level == 2);
420+
assert!(m == 1);
421+
}
422+
do "crate2::mod2".to_c_str().with_ref |ptr| {
423+
let entry= &ModEntry {name: ptr, log_level: level};
424+
let m = update_entry(dirs, transmute(entry));
425+
assert!(*entry.log_level == 3);
426+
assert!(m == 1);
427+
}
428+
}
429+
}

0 commit comments

Comments
 (0)