Skip to content

Commit

Permalink
[rust] Include mixed output (INFO, WARN, DEBUG, etc. to stderr and mi…
Browse files Browse the repository at this point in the history
…nimal JSON to stdout) (SeleniumHQ#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]>
  • Loading branch information
2 people authored and sandeepsuryaprasad committed Oct 29, 2024
1 parent 945ed3d commit 383d1ed
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 21 deletions.
76 changes: 60 additions & 16 deletions rust/src/logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@

use crate::config::{BooleanKey, StringKey};
use crate::metadata::now_unix_timestamp;
use env_logger::Target::Stdout;

use env_logger::Target::{Stderr, Stdout};
use env_logger::DEFAULT_FILTER_ENV;
use log::LevelFilter::{Debug, Info, Trace};
use log::{Level, LevelFilter};
use serde::{Deserialize, Serialize};
use std::cell::RefCell;
use std::env;
use std::fmt::Display;
use std::ops::Deref;
use std::str::FromStr;

pub const DRIVER_PATH: &str = "Driver path: ";
Expand All @@ -37,6 +37,7 @@ enum OutputType {
Logger,
Json,
Shell,
Mixed,
}

#[derive(Default)]
Expand All @@ -45,6 +46,7 @@ pub struct Logger {
trace: bool,
output: OutputType,
json: RefCell<JsonOutput>,
minimal_json: RefCell<MinimalJson>,
}

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

#[derive(Default, Serialize, Deserialize)]
pub struct MinimalJson {
pub driver_path: String,
pub browser_path: String,
pub error: String,
}

impl Logger {
pub fn new() -> Self {
let debug = BooleanKey("debug", false).get_value();
Expand All @@ -82,13 +91,15 @@ impl Logger {
output_type = OutputType::Json;
} else if output.eq_ignore_ascii_case("shell") {
output_type = OutputType::Shell;
} else if output.eq_ignore_ascii_case("mixed") {
output_type = OutputType::Mixed;
} else {
output_type = OutputType::Logger;
}
match output_type {
OutputType::Logger => {
OutputType::Logger | OutputType::Mixed => {
if env::var(DEFAULT_FILTER_ENV).unwrap_or_default().is_empty() {
let filter = if !log_level.is_empty() {
let mut filter = if !log_level.is_empty() {
LevelFilter::from_str(log_level).unwrap_or(Info)
} else {
let mut filter = match debug {
Expand All @@ -100,9 +111,17 @@ impl Logger {
}
filter
};
if trace {
filter = Trace
}
let target = if output_type == OutputType::Logger {
Stdout
} else {
Stderr
};
env_logger::Builder::new()
.filter_module(env!("CARGO_CRATE_NAME"), filter)
.target(Stdout)
.target(target)
.format_target(false)
.format_timestamp_millis()
.try_init()
Expand Down Expand Up @@ -131,6 +150,7 @@ impl Logger {
browser_path: "".to_string(),
},
}),
minimal_json: RefCell::new(Default::default()),
}
}

Expand Down Expand Up @@ -173,12 +193,11 @@ impl Logger {
}
if level == Level::Info || level <= Level::Error {
if message.starts_with(DRIVER_PATH) {
let driver_path = message.replace(DRIVER_PATH, "");
self.json.borrow_mut().result.driver_path = driver_path.to_owned();
self.json.borrow_mut().result.message = driver_path;
self.json.borrow_mut().result.driver_path =
self.clean_driver_path(&message);
} else if message.starts_with(BROWSER_PATH) {
let browser_path = message.replace(BROWSER_PATH, "");
self.json.borrow_mut().result.browser_path = browser_path;
self.json.borrow_mut().result.browser_path =
self.clean_browser_path(&message);
} else {
self.json.borrow_mut().result.message = message;
}
Expand All @@ -192,11 +211,31 @@ impl Logger {
}
}
_ => {
if self.output == OutputType::Mixed && level == Level::Info || level <= Level::Error
{
if message.starts_with(DRIVER_PATH) {
self.minimal_json.borrow_mut().driver_path =
self.clean_driver_path(&message);
} else if message.starts_with(BROWSER_PATH) {
self.minimal_json.borrow_mut().browser_path =
self.clean_browser_path(&message);
} else {
self.minimal_json.borrow_mut().error = message.clone();
}
}
log::log!(level, "{}", message);
}
}
}

fn clean_driver_path(&self, message: &str) -> String {
message.replace(DRIVER_PATH, "")
}

fn clean_browser_path(&self, message: &str) -> String {
message.replace(BROWSER_PATH, "")
}

fn create_json_log(&self, message: String, level: Level) -> Logs {
Logs {
level: level.to_string().to_uppercase(),
Expand All @@ -205,17 +244,22 @@ impl Logger {
}
}

fn get_json_blog<T>(&self, json_output: &T) -> String
where
T: Serialize,
{
serde_json::to_string_pretty(json_output).unwrap()
}

pub fn set_code(&self, code: i32) {
self.json.borrow_mut().result.code = code;
}

pub fn flush(&self) {
let json_output = &self.json.borrow();
let json = json_output.deref();
if !json.logs.is_empty() {
print!("{}", serde_json::to_string_pretty(json).unwrap());
} else if self.output == OutputType::Json {
panic!("JSON output has been specified, but no entries have been collected")
if self.output == OutputType::Json {
print!("{}", self.get_json_blog(&self.json));
} else if self.output == OutputType::Mixed {
print!("{}", self.get_json_blog(&self.minimal_json));
}
}
}
3 changes: 2 additions & 1 deletion rust/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ struct Cli {
#[clap(long, value_parser)]
browser_mirror_url: Option<String>,

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

Expand Down
4 changes: 2 additions & 2 deletions rust/tests/grid_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ fn grid_latest_test() {
let output_code = json.result.code;
assert_eq!(output_code, 0);

let jar = Path::new(&json.result.message);
let jar = Path::new(&json.result.driver_path);
assert!(jar.exists());

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

let json: JsonOutput = serde_json::from_str(output).unwrap();
let jar = Path::new(&json.result.message);
let jar = Path::new(&json.result.driver_path);
let jar_name = jar.file_name().unwrap().to_str().unwrap();
assert!(jar_name.contains(grid_version));
}
Expand Down
26 changes: 24 additions & 2 deletions rust/tests/output_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
// under the License.

use assert_cmd::Command;
use selenium_manager::logger::{JsonOutput, DRIVER_PATH};
use selenium_manager::logger::{JsonOutput, MinimalJson, DRIVER_PATH};
use std::path::Path;
use std::str;

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

let driver = Path::new(&json.result.message);
let driver = Path::new(&json.result.driver_path);
assert!(driver.exists());
}

Expand All @@ -55,3 +55,25 @@ fn shell_output_test() {
println!("{}", output);
assert!(output.contains(DRIVER_PATH));
}

#[test]
fn mixed_output_test() {
let mut cmd = Command::new(env!("CARGO_BIN_EXE_selenium-manager"));
cmd.args(["--browser", "chrome", "--output", "mixed"])
.assert()
.success()
.code(0);

let stdout = &cmd.unwrap().stdout;
let output = str::from_utf8(stdout).unwrap();
println!("stdout: {}", output);

let json: MinimalJson = serde_json::from_str(output).unwrap();
let driver = Path::new(&json.driver_path);
assert!(driver.exists());

let stderr = &cmd.unwrap().stderr;
let err_output = str::from_utf8(stderr).unwrap();
println!("stderr: {}", err_output);
assert!(!err_output.is_empty());
}

0 comments on commit 383d1ed

Please sign in to comment.