Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 10 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,22 +59,17 @@ codspeed run pytest ./tests --codspeed
codspeed run pnpm vitest bench
```

## Advanced usage

### Installing tools before running

You can install executors and instruments before running the benchmark with the `setup` command:

```bash
codspeed setup
```
Usage: codspeed run [OPTIONS] [COMMAND]...

Arguments:
[COMMAND]... The bench command to run

Options:
--upload-url <UPLOAD_URL>
The upload URL to use for uploading the results, useful for on-premises installations
--token <TOKEN>
The token to use for uploading the results, if not provided it will be read from the CODSPEED_TOKEN environment variable
--working-directory <WORKING_DIRECTORY>
The directory where the command will be executed
-h, --help
Print help
```

This is especially useful when configuring environments with tools such as docker.

### Logging level

Expand Down
18 changes: 16 additions & 2 deletions src/app.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use crate::{
api_client::CodSpeedAPIClient, auth, local_logger::CODSPEED_U8_COLOR_CODE, prelude::*, run,
api_client::CodSpeedAPIClient,
auth,
local_logger::{init_local_logger, CODSPEED_U8_COLOR_CODE},
prelude::*,
run, setup,
};
use clap::{
builder::{styling, Styles},
Expand Down Expand Up @@ -37,17 +41,27 @@ pub struct Cli {
enum Commands {
/// Run the bench command and upload the results to CodSpeed
Run(run::RunArgs),
/// Commands related to authentication with CodSpeed
/// Manage the CLI authentication state
Auth(auth::AuthArgs),
/// Pre-install the codspeed executors
Setup,
}

pub async fn run() -> Result<()> {
let cli = Cli::parse();
let api_client = CodSpeedAPIClient::try_from(&cli)?;

match cli.command {
Commands::Run(_) => {} // Run is responsible for its own logger initialization
_ => {
init_local_logger()?;
}
}

match cli.command {
Commands::Run(args) => run::run(args, &api_client).await?,
Commands::Auth(args) => auth::run(args, &api_client).await?,
Commands::Setup => setup::setup().await?,
}
Ok(())
}
10 changes: 0 additions & 10 deletions src/auth.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use std::time::Duration;

use crate::local_logger::get_local_logger;
use crate::{api_client::CodSpeedAPIClient, config::CodSpeedConfig, prelude::*};
use clap::{Args, Subcommand};
use console::style;
use simplelog::CombinedLogger;
use tokio::time::{sleep, Instant};

#[derive(Debug, Args)]
Expand All @@ -19,15 +17,7 @@ enum AuthCommands {
Login,
}

fn init_logger() -> Result<()> {
let logger = get_local_logger();
CombinedLogger::init(vec![logger])?;
Ok(())
}

pub async fn run(args: AuthArgs, api_client: &CodSpeedAPIClient) -> Result<()> {
init_logger()?;

match args.command {
AuthCommands::Login => login(api_client).await?,
}
Expand Down
20 changes: 11 additions & 9 deletions src/local_logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ use std::{
time::Duration,
};

use crate::prelude::*;
use console::{style, Style};
use indicatif::{ProgressBar, ProgressStyle};
use lazy_static::lazy_static;
use log::Log;
use simplelog::SharedLogger;
use simplelog::{CombinedLogger, SharedLogger};
use std::io::Write;

use crate::logger::{get_group_event, GroupEvent};

pub const CODSPEED_U8_COLOR_CODE: u8 = 208; // #FF8700
const BLACK_U8_COLOR_CODE: u8 = 16; // #000

lazy_static! {
pub static ref SPINNER: Arc<Mutex<Option<ProgressBar>>> = Arc::new(Mutex::new(None));
Expand Down Expand Up @@ -67,13 +67,11 @@ impl Log for LocalLogger {
match group_event {
GroupEvent::Start(name) | GroupEvent::StartOpened(name) => {
println!(
" {}",
style(format!(" {} ", name.to_uppercase()))
"\n{}",
style(format!("►►► {} ", name))
.bold()
.color256(BLACK_U8_COLOR_CODE)
.on_color256(CODSPEED_U8_COLOR_CODE)
.color256(CODSPEED_U8_COLOR_CODE)
);
println!();

if *IS_TTY {
let spinner = ProgressBar::new_spinner();
Expand All @@ -99,10 +97,8 @@ impl Log for LocalLogger {
let mut spinner = SPINNER.lock().unwrap();
if let Some(spinner) = spinner.as_mut() {
spinner.finish_and_clear();
println!();
}
}
println!();
}
}

Expand Down Expand Up @@ -158,6 +154,12 @@ pub fn get_local_logger() -> Box<dyn SharedLogger> {
Box::new(LocalLogger::new())
}

pub fn init_local_logger() -> Result<()> {
let logger = get_local_logger();
CombinedLogger::init(vec![logger])?;
Ok(())
}

pub fn clean_logger() {
let mut spinner = SPINNER.lock().unwrap();
if let Some(spinner) = spinner.as_mut() {
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mod logger;
mod prelude;
mod request_client;
mod run;
mod setup;

use console::style;
use lazy_static::lazy_static;
Expand Down
12 changes: 9 additions & 3 deletions src/run/check_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,18 @@ pub fn check_system(system_info: &SystemInfo) -> Result<()> {

match system_info.arch.as_str() {
"x86_64" | "aarch64" => {
warn!("Unsupported system: {:?}", system_info);
warn!("Continuing with best effort support");
warn!(
"Unofficially supported system: {} {}. Continuing with best effort support.",
system_info.os, system_info.os_version
);
return Ok(());
}
_ => {}
}

bail!("Unsupported system: {:?}", system_info);
bail!(
"Unsupported system: {} {}",
system_info.os,
system_info.os_version
);
}
2 changes: 2 additions & 0 deletions src/run/helpers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod download_file;
mod find_repository_root;
mod get_env_var;
mod parse_git_remote;

pub use download_file::download_file;
pub use find_repository_root::find_repository_root;
pub use get_env_var::get_env_variable;
pub use parse_git_remote::*;
30 changes: 28 additions & 2 deletions src/run/instruments/mongo_tracer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::{
env,
io::Read,
path::{Path, PathBuf},
process::{Child, Command, Stdio},
Expand All @@ -10,8 +11,8 @@ use reqwest::Client;
use tokio::fs;
use url::Url;

use crate::prelude::*;
use crate::run::helpers::get_env_variable;
use crate::{prelude::*, run::helpers::download_file};
use crate::{run::helpers::get_env_variable, MONGODB_TRACER_VERSION};

use super::MongoDBConfig;

Expand Down Expand Up @@ -228,6 +229,31 @@ impl MongoTracer {
}
}

pub async fn install_mongodb_tracer() -> Result<()> {
debug!("Installing mongodb-tracer");
// TODO: release the tracer and update this url
let installer_url = format!("https://codspeed-public-assets.s3.eu-west-1.amazonaws.com/mongo-tracer/{MONGODB_TRACER_VERSION}/cs-mongo-tracer-installer.sh");
let installer_path = env::temp_dir().join("cs-mongo-tracer-installer.sh");
download_file(
&Url::parse(installer_url.as_str()).unwrap(),
&installer_path,
)
.await?;

let output = Command::new("bash")
.arg(installer_path.to_str().unwrap())
.stdout(Stdio::piped())
.output()
.map_err(|_| anyhow!("Failed to install mongo-tracer"))?;

if !output.status.success() {
info!("stdout: {}", String::from_utf8_lossy(&output.stdout));
error!("stderr: {}", String::from_utf8_lossy(&output.stderr));
bail!("Failed to install mongo-tracer");
}
Ok(())
}

#[cfg(test)]
mod tests {
use std::ffi::OsStr;
Expand Down
19 changes: 12 additions & 7 deletions src/run/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ use crate::run::{config::Config, logger::Logger};
use crate::VERSION;
use check_system::SystemInfo;
use clap::Args;
use instruments::mongo_tracer::MongoTracer;
use instruments::mongo_tracer::{install_mongodb_tracer, MongoTracer};
use run_environment::interfaces::RunEnvironment;
use runner::get_run_data;

mod check_system;
mod helpers;
pub mod check_system;
pub mod helpers;
mod instruments;
mod poll_results;
pub mod run_environment;
mod runner;
pub mod runner;
mod uploader;

pub mod config;
Expand Down Expand Up @@ -120,14 +120,19 @@ pub async fn run(args: RunArgs, api_client: &CodSpeedAPIClient) -> Result<()> {
let mode = runner::get_mode()?;
let executor = runner::get_executor_from_mode(mode);

let run_data = get_run_data()?;

if !config.skip_setup {
start_group!("Preparing the environment");
executor.setup(&config, &system_info, &run_data).await?;
executor.setup(&system_info).await?;
// TODO: refactor and move directly in the Instruments struct as a `setup` method
if config.instruments.is_mongodb_enabled() {
install_mongodb_tracer().await?;
}
info!("Environment ready");
end_group!();
}

let run_data = get_run_data()?;

start_opened_group!("Running the benchmarks");

// TODO: refactor and move directly in the Instruments struct as a `start` method
Expand Down
9 changes: 3 additions & 6 deletions src/run/runner/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,9 @@ use async_trait::async_trait;
pub trait Executor {
fn name(&self) -> ExecutorName;

async fn setup(
&self,
config: &Config,
system_info: &SystemInfo,
run_data: &RunData,
) -> Result<()>;
async fn setup(&self, _system_info: &SystemInfo) -> Result<()> {
Ok(())
}

/// Runs the executor
async fn run(
Expand Down
4 changes: 4 additions & 0 deletions src/run/runner/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ pub fn get_executor_from_mode(mode: RunnerMode) -> Box<dyn Executor> {
}
}

pub fn get_all_executors() -> Vec<Box<dyn Executor>> {
vec![Box::new(ValgrindExecutor), Box::new(WallTimeExecutor)]
}

pub fn get_run_data() -> Result<RunData> {
let profile_folder = create_profile_folder()?;
Ok(RunData { profile_folder })
Expand Down
13 changes: 4 additions & 9 deletions src/run/runner/valgrind/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use crate::run::runner::executor::Executor;
use crate::run::runner::{ExecutorName, RunData};
use crate::run::{check_system::SystemInfo, config::Config};

use super::{helpers::perf_maps::harvest_perf_maps, measure, setup::setup};
use super::setup::install_valgrind;
use super::{helpers::perf_maps::harvest_perf_maps, measure};

pub struct ValgrindExecutor;

Expand All @@ -16,14 +17,8 @@ impl Executor for ValgrindExecutor {
ExecutorName::Valgrind
}

async fn setup(
&self,
config: &Config,
system_info: &SystemInfo,
_run_data: &RunData,
) -> Result<()> {
setup(system_info, config).await?;

async fn setup(&self, system_info: &SystemInfo) -> Result<()> {
install_valgrind(system_info).await?;
Ok(())
}

Expand Down
1 change: 0 additions & 1 deletion src/run/runner/valgrind/helpers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
pub mod download_file;
pub mod ignored_objects_path;
pub mod introspected_nodejs;
pub mod perf_maps;
Loading
Loading