Skip to content
Open
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
20 changes: 3 additions & 17 deletions src/executor/helpers/run_command_with_log_pipe.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::executor::EXECUTOR_TARGET;
use crate::local_logger::rolling_buffer::ROLLING_BUFFER;
use crate::local_logger::suspend_progress_bar;
use crate::local_logger::write_command_output;
use crate::prelude::*;
use std::future::Future;
use std::io::{Read, Write};
Expand All @@ -26,19 +25,6 @@ where
F: FnOnce(std::process::Child) -> Fut,
Fut: Future<Output = anyhow::Result<ExitStatus>>,
{
/// Write text to the rolling buffer if active, otherwise write raw bytes to the writer.
fn write_to_rolling_buffer_or_output(text: &str, raw_bytes: &[u8], writer: &mut impl Write) {
if let Ok(mut guard) = ROLLING_BUFFER.lock() {
if let Some(rb) = guard.as_mut() {
if rb.is_active() {
rb.push_lines(text);
return;
}
}
}
suspend_progress_bar(|| writer.write_all(raw_bytes).unwrap());
}

fn log_tee(
mut reader: impl Read,
mut writer: impl Write,
Expand All @@ -55,7 +41,7 @@ where
if !line_buffer.is_empty() {
let text = String::from_utf8_lossy(&line_buffer);
trace!(target: EXECUTOR_TARGET, "{prefix}{text}");
write_to_rolling_buffer_or_output(&text, &line_buffer, &mut writer);
write_command_output(&text, &line_buffer, &mut writer);
}
break;
}
Expand All @@ -71,7 +57,7 @@ where
let to_flush = &line_buffer[..=last_newline_pos];
let text = String::from_utf8_lossy(to_flush);
trace!(target: EXECUTOR_TARGET, "{prefix}{text}");
write_to_rolling_buffer_or_output(&text, to_flush, &mut writer);
write_command_output(&text, to_flush, &mut writer);

// Keep the remainder in the buffer
line_buffer = line_buffer[last_newline_pos + 1..].to_vec();
Expand Down
12 changes: 5 additions & 7 deletions src/executor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ mod valgrind;
mod wall_time;

use crate::instruments::mongo_tracer::{MongoTracer, install_mongodb_tracer};
use crate::local_logger::rolling_buffer::{activate_rolling_buffer, deactivate_rolling_buffer};
use crate::prelude::*;
use crate::runner_mode::RunnerMode;
use crate::system::SystemInfo;
Expand Down Expand Up @@ -158,7 +157,7 @@ pub async fn run_executor(
orchestrator: &Orchestrator,
execution_context: &ExecutionContext,
setup_cache_dir: Option<&Path>,
rolling_buffer_label: Option<&str>,
display_label: Option<&str>,
) -> Result<()> {
match executor.support_level(&orchestrator.system_info) {
ExecutorSupport::Unsupported => {
Expand Down Expand Up @@ -199,12 +198,11 @@ pub async fn run_executor(
None
};

if let Some(label) = rolling_buffer_label {
activate_rolling_buffer(label);
}
let display_guard =
display_label.and_then(|label| orchestrator.provider.start_command_display(label));
let run_result = executor.run(execution_context, &mongo_tracer).await;
if rolling_buffer_label.is_some() {
deactivate_rolling_buffer();
if let Some(guard) = display_guard {
guard.finish_with(run_result.is_ok());
}
run_result?;

Expand Down
5 changes: 2 additions & 3 deletions src/executor/orchestrator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,15 +150,14 @@ impl Orchestrator {

let ctx = ExecutionContext::new(config, profile_folder);

let rolling_buffer_label =
(!self.config.show_full_output).then_some(part.label.as_str());
let display_label = (!self.config.show_full_output).then_some(part.label.as_str());

run_executor(
executor.as_mut(),
self,
&ctx,
setup_cache_dir,
rolling_buffer_label,
display_label,
)
.await?;

Expand Down
53 changes: 39 additions & 14 deletions src/local_logger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ pub mod rolling_buffer;

use std::{
env,
sync::{Arc, Mutex},
sync::{
Arc, Mutex,
atomic::{AtomicBool, Ordering},
},
time::Duration,
};

Expand Down Expand Up @@ -37,6 +40,24 @@ static CURRENT_GROUP_NAME: LazyLock<Arc<Mutex<Option<String>>>> =
/// Flushed in `draw_frame` before each redraw.
static DEFERRED_LOGS: LazyLock<Mutex<Vec<DeferredLog>>> = LazyLock::new(|| Mutex::new(Vec::new()));

/// Set while a rolling buffer owns the terminal region. `LocalLogger` then
/// defers its records (see [`DEFERRED_LOGS`]) instead of printing directly,
/// as any direct stderr output would corrupt the frame.
static ROLLING_BUFFER_ACTIVE: AtomicBool = AtomicBool::new(false);

fn set_rolling_buffer_active(active: bool) {
ROLLING_BUFFER_ACTIVE.store(active, Ordering::Relaxed);
}

/// Write a chunk of benchmark command output to the terminal: into the rolling
/// buffer when one is active, otherwise verbatim to `writer`.
pub(crate) fn write_command_output(text: &str, raw_bytes: &[u8], writer: &mut impl Write) {
if rolling_buffer::try_push(text) {
return;
}
suspend_progress_bar(|| writer.write_all(raw_bytes).unwrap());
}

/// A snapshot of a log record that can be stored across the rolling-buffer
/// lifetime (the original `log::Record` borrows data and cannot be kept).
struct DeferredLog {
Expand Down Expand Up @@ -143,20 +164,15 @@ impl Log for LocalLogger {
// When the rolling buffer is active it owns the terminal region and uses
// cursor manipulation to redraw. Any direct stderr output would corrupt
// the display, so we defer log records and flush them before each redraw.
{
use rolling_buffer::ROLLING_BUFFER;
if let Ok(guard) = ROLLING_BUFFER.try_lock() {
if guard.as_ref().is_some_and(|rb| rb.is_active()) {
if let Ok(mut deferred) = DEFERRED_LOGS.try_lock() {
deferred.push(DeferredLog {
level: record.level(),
message: format!("{}", record.args()),
target: record.target().to_string(),
});
}
return;
}
if ROLLING_BUFFER_ACTIVE.load(Ordering::Relaxed) {
if let Ok(mut deferred) = DEFERRED_LOGS.try_lock() {
deferred.push(DeferredLog {
level: record.level(),
message: format!("{}", record.args()),
target: record.target().to_string(),
});
}
return;
}

suspend_progress_bar(|| print_record(record));
Expand Down Expand Up @@ -190,6 +206,15 @@ pub(crate) fn format_checkmark(label: &str, dim: bool) -> String {
)
}

/// Format a failure cross with a label.
pub(crate) fn format_cross(label: &str) -> String {
format!(
" {} {}",
style(Icon::Error.to_string()).red().bold(),
label
)
}

/// Format elapsed duration in a compact human-readable way
fn format_elapsed(duration: Duration) -> String {
let secs = duration.as_secs();
Expand Down
Loading