Skip to content

Commit 95cd6f5

Browse files
bonigarciadiemol
andauthored
[rust] Include mixed output (INFO, WARN, DEBUG, etc. to stderr and minimal JSON to stdout) (#13414)
* [rust] Include mixed output (INFO, WARN, DEBUG, etc. to stderr and minimal JSON to stdout) * [rust] Include field for error message in the minimal JSON * [rust] Change field message to error * [rust] Fix logger module --------- Co-authored-by: Diego Molina <[email protected]>
1 parent 22386f6 commit 95cd6f5

File tree

4 files changed

+88
-21
lines changed

4 files changed

+88
-21
lines changed

rust/src/logger.rs

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@
1717

1818
use crate::config::{BooleanKey, StringKey};
1919
use crate::metadata::now_unix_timestamp;
20-
use env_logger::Target::Stdout;
20+
21+
use env_logger::Target::{Stderr, Stdout};
2122
use env_logger::DEFAULT_FILTER_ENV;
2223
use log::LevelFilter::{Debug, Info, Trace};
2324
use log::{Level, LevelFilter};
2425
use serde::{Deserialize, Serialize};
2526
use std::cell::RefCell;
2627
use std::env;
2728
use std::fmt::Display;
28-
use std::ops::Deref;
2929
use std::str::FromStr;
3030

3131
pub const DRIVER_PATH: &str = "Driver path: ";
@@ -37,6 +37,7 @@ enum OutputType {
3737
Logger,
3838
Json,
3939
Shell,
40+
Mixed,
4041
}
4142

4243
#[derive(Default)]
@@ -45,6 +46,7 @@ pub struct Logger {
4546
trace: bool,
4647
output: OutputType,
4748
json: RefCell<JsonOutput>,
49+
minimal_json: RefCell<MinimalJson>,
4850
}
4951

5052
#[derive(Default, Serialize, Deserialize)]
@@ -68,6 +70,13 @@ pub struct JsonOutput {
6870
pub result: Result,
6971
}
7072

73+
#[derive(Default, Serialize, Deserialize)]
74+
pub struct MinimalJson {
75+
pub driver_path: String,
76+
pub browser_path: String,
77+
pub error: String,
78+
}
79+
7180
impl Logger {
7281
pub fn new() -> Self {
7382
let debug = BooleanKey("debug", false).get_value();
@@ -82,13 +91,15 @@ impl Logger {
8291
output_type = OutputType::Json;
8392
} else if output.eq_ignore_ascii_case("shell") {
8493
output_type = OutputType::Shell;
94+
} else if output.eq_ignore_ascii_case("mixed") {
95+
output_type = OutputType::Mixed;
8596
} else {
8697
output_type = OutputType::Logger;
8798
}
8899
match output_type {
89-
OutputType::Logger => {
100+
OutputType::Logger | OutputType::Mixed => {
90101
if env::var(DEFAULT_FILTER_ENV).unwrap_or_default().is_empty() {
91-
let filter = if !log_level.is_empty() {
102+
let mut filter = if !log_level.is_empty() {
92103
LevelFilter::from_str(log_level).unwrap_or(Info)
93104
} else {
94105
let mut filter = match debug {
@@ -100,9 +111,17 @@ impl Logger {
100111
}
101112
filter
102113
};
114+
if trace {
115+
filter = Trace
116+
}
117+
let target = if output_type == OutputType::Logger {
118+
Stdout
119+
} else {
120+
Stderr
121+
};
103122
env_logger::Builder::new()
104123
.filter_module(env!("CARGO_CRATE_NAME"), filter)
105-
.target(Stdout)
124+
.target(target)
106125
.format_target(false)
107126
.format_timestamp_millis()
108127
.try_init()
@@ -131,6 +150,7 @@ impl Logger {
131150
browser_path: "".to_string(),
132151
},
133152
}),
153+
minimal_json: RefCell::new(Default::default()),
134154
}
135155
}
136156

@@ -173,12 +193,11 @@ impl Logger {
173193
}
174194
if level == Level::Info || level <= Level::Error {
175195
if message.starts_with(DRIVER_PATH) {
176-
let driver_path = message.replace(DRIVER_PATH, "");
177-
self.json.borrow_mut().result.driver_path = driver_path.to_owned();
178-
self.json.borrow_mut().result.message = driver_path;
196+
self.json.borrow_mut().result.driver_path =
197+
self.clean_driver_path(&message);
179198
} else if message.starts_with(BROWSER_PATH) {
180-
let browser_path = message.replace(BROWSER_PATH, "");
181-
self.json.borrow_mut().result.browser_path = browser_path;
199+
self.json.borrow_mut().result.browser_path =
200+
self.clean_browser_path(&message);
182201
} else {
183202
self.json.borrow_mut().result.message = message;
184203
}
@@ -192,11 +211,31 @@ impl Logger {
192211
}
193212
}
194213
_ => {
214+
if self.output == OutputType::Mixed && level == Level::Info || level <= Level::Error
215+
{
216+
if message.starts_with(DRIVER_PATH) {
217+
self.minimal_json.borrow_mut().driver_path =
218+
self.clean_driver_path(&message);
219+
} else if message.starts_with(BROWSER_PATH) {
220+
self.minimal_json.borrow_mut().browser_path =
221+
self.clean_browser_path(&message);
222+
} else {
223+
self.minimal_json.borrow_mut().error = message.clone();
224+
}
225+
}
195226
log::log!(level, "{}", message);
196227
}
197228
}
198229
}
199230

231+
fn clean_driver_path(&self, message: &str) -> String {
232+
message.replace(DRIVER_PATH, "")
233+
}
234+
235+
fn clean_browser_path(&self, message: &str) -> String {
236+
message.replace(BROWSER_PATH, "")
237+
}
238+
200239
fn create_json_log(&self, message: String, level: Level) -> Logs {
201240
Logs {
202241
level: level.to_string().to_uppercase(),
@@ -205,17 +244,22 @@ impl Logger {
205244
}
206245
}
207246

247+
fn get_json_blog<T>(&self, json_output: &T) -> String
248+
where
249+
T: Serialize,
250+
{
251+
serde_json::to_string_pretty(json_output).unwrap()
252+
}
253+
208254
pub fn set_code(&self, code: i32) {
209255
self.json.borrow_mut().result.code = code;
210256
}
211257

212258
pub fn flush(&self) {
213-
let json_output = &self.json.borrow();
214-
let json = json_output.deref();
215-
if !json.logs.is_empty() {
216-
print!("{}", serde_json::to_string_pretty(json).unwrap());
217-
} else if self.output == OutputType::Json {
218-
panic!("JSON output has been specified, but no entries have been collected")
259+
if self.output == OutputType::Json {
260+
print!("{}", self.get_json_blog(&self.json));
261+
} else if self.output == OutputType::Mixed {
262+
print!("{}", self.get_json_blog(&self.minimal_json));
219263
}
220264
}
221265
}

rust/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ struct Cli {
7777
#[clap(long, value_parser)]
7878
browser_mirror_url: Option<String>,
7979

80-
/// Output type: LOGGER (using INFO, WARN, etc.), JSON (custom JSON notation), or SHELL (Unix-like)
80+
/// Output type: LOGGER (using INFO, WARN, etc.), JSON (custom JSON notation), SHELL (Unix-like),
81+
/// or MIXED (INFO, WARN, DEBUG, etc. to stderr and minimal JSON to stdout)
8182
#[clap(long, value_parser, default_value = "LOGGER")]
8283
output: String,
8384

rust/tests/grid_tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ fn grid_latest_test() {
4343
let output_code = json.result.code;
4444
assert_eq!(output_code, 0);
4545

46-
let jar = Path::new(&json.result.message);
46+
let jar = Path::new(&json.result.driver_path);
4747
assert!(jar.exists());
4848

4949
let jar_name = jar.file_name().unwrap().to_str().unwrap();
@@ -66,7 +66,7 @@ fn grid_version_test(#[case] grid_version: &str) {
6666
println!("{}", output);
6767

6868
let json: JsonOutput = serde_json::from_str(output).unwrap();
69-
let jar = Path::new(&json.result.message);
69+
let jar = Path::new(&json.result.driver_path);
7070
let jar_name = jar.file_name().unwrap().to_str().unwrap();
7171
assert!(jar_name.contains(grid_version));
7272
}

rust/tests/output_tests.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
// under the License.
1717

1818
use assert_cmd::Command;
19-
use selenium_manager::logger::{JsonOutput, DRIVER_PATH};
19+
use selenium_manager::logger::{JsonOutput, MinimalJson, DRIVER_PATH};
2020
use std::path::Path;
2121
use std::str;
2222

@@ -38,7 +38,7 @@ fn json_output_test() {
3838
let output_code = json.result.code;
3939
assert_eq!(output_code, 0);
4040

41-
let driver = Path::new(&json.result.message);
41+
let driver = Path::new(&json.result.driver_path);
4242
assert!(driver.exists());
4343
}
4444

@@ -55,3 +55,25 @@ fn shell_output_test() {
5555
println!("{}", output);
5656
assert!(output.contains(DRIVER_PATH));
5757
}
58+
59+
#[test]
60+
fn mixed_output_test() {
61+
let mut cmd = Command::new(env!("CARGO_BIN_EXE_selenium-manager"));
62+
cmd.args(["--browser", "chrome", "--output", "mixed"])
63+
.assert()
64+
.success()
65+
.code(0);
66+
67+
let stdout = &cmd.unwrap().stdout;
68+
let output = str::from_utf8(stdout).unwrap();
69+
println!("stdout: {}", output);
70+
71+
let json: MinimalJson = serde_json::from_str(output).unwrap();
72+
let driver = Path::new(&json.driver_path);
73+
assert!(driver.exists());
74+
75+
let stderr = &cmd.unwrap().stderr;
76+
let err_output = str::from_utf8(stderr).unwrap();
77+
println!("stderr: {}", err_output);
78+
assert!(!err_output.is_empty());
79+
}

0 commit comments

Comments
 (0)