pub struct LoggingRunner<R: ProcessRunner = JobRunner> { /* private fields */ }Expand description
A ProcessRunner decorator that reports every command it runs to a
CommandObserver, then forwards the real runner’s result unchanged.
It adds only observation — the wrapped runner’s behaviour, results, and errors
are passed through verbatim. Construct one with new (a
StderrObserver) or with_observer (a custom sink),
then hand it to any client’s with_runner builder:
use processkit::JobRunner;
use vcs_cli_support::logging::LoggingRunner;
// A boxed runner erases the concrete type, so the same client type works
// whether or not logging is enabled.
let runner: Box<dyn processkit::ProcessRunner> =
Box::new(LoggingRunner::new(JobRunner::new(), "vcs-mcp"));Implementations§
Source§impl<R: ProcessRunner> LoggingRunner<R>
impl<R: ProcessRunner> LoggingRunner<R>
Sourcepub fn new(inner: R, tag: impl Into<Arc<str>>) -> Self
pub fn new(inner: R, tag: impl Into<Arc<str>>) -> Self
Wrap inner, logging each command to stderr with the tag tag (via
StderrObserver).
Sourcepub fn with_observer(inner: R, observer: Arc<dyn CommandObserver>) -> Self
pub fn with_observer(inner: R, observer: Arc<dyn CommandObserver>) -> Self
Wrap inner, reporting each command to observer.
Sourcepub fn observer(&self) -> &Arc<dyn CommandObserver> ⓘ
pub fn observer(&self) -> &Arc<dyn CommandObserver> ⓘ
The observer this runner reports to.
Trait Implementations§
Source§impl<R: ProcessRunner + Debug> Debug for LoggingRunner<R>
impl<R: ProcessRunner + Debug> Debug for LoggingRunner<R>
Source§impl<R: ProcessRunner> ProcessRunner for LoggingRunner<R>
impl<R: ProcessRunner> ProcessRunner for LoggingRunner<R>
Source§fn output_string<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<ProcessResult<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn output_string<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<ProcessResult<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Run
command to completion, capturing stdout/stderr and the exit code.
A non-zero exit is reported in the result, not raised.Source§fn output_bytes<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<ProcessResult<Vec<u8>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn output_bytes<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<ProcessResult<Vec<u8>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Run
command to completion, capturing stdout as raw bytes (output_string
captures it as lossy-UTF-8 text); stderr is still text. For binary tools
— git cat-file, tar -c, an image transcoder — whose stdout is not
UTF-8. Read moreSource§fn start<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<RunningProcess>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn start<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<RunningProcess>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Start
command and return a live RunningProcess for streaming,
readiness probes, or incremental consumption. Read moreAuto Trait Implementations§
impl<R = JobRunner> !RefUnwindSafe for LoggingRunner<R>
impl<R = JobRunner> !UnwindSafe for LoggingRunner<R>
impl<R> Freeze for LoggingRunner<R>where
R: Freeze,
impl<R> Send for LoggingRunner<R>
impl<R> Sync for LoggingRunner<R>
impl<R> Unpin for LoggingRunner<R>where
R: Unpin,
impl<R> UnsafeUnpin for LoggingRunner<R>where
R: UnsafeUnpin,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> ProcessRunnerExt for Twhere
T: ProcessRunner + ?Sized,
impl<T> ProcessRunnerExt for Twhere
T: ProcessRunner + ?Sized,
Source§fn run<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<String, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: Sync + 'async_trait,
fn run<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<String, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: Sync + 'async_trait,
Run, require an accepted exit, and return trimmed stdout. Accepted is
0 by default, widened by Command::ok_codes;
any other code is ErrorReason::Exit.Source§fn run_unit<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: Sync + 'async_trait,
fn run_unit<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: Sync + 'async_trait,
Run for the side effect: require an accepted exit (
0, or any code in
Command::ok_codes), discard the output.Source§fn exit_code<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<i32, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: Sync + 'async_trait,
fn exit_code<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<i32, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: Sync + 'async_trait,
Run and return just the exit code. A run that produced no code surfaces as
an error — a timeout as
ErrorReason::Timeout, a
signal-kill as ErrorReason::Signalled — rather than a
synthetic sentinel, mirroring
ensure_success.Source§fn probe<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<bool, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: Sync + 'async_trait,
fn probe<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<bool, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: Sync + 'async_trait,
Run a predicate command and read its exit code as a boolean: exit
0 →
Ok(true), exit 1 → Ok(false), anything else → Err (other code as
ErrorReason::Exit, timeout as
ErrorReason::Timeout, signal-kill as
ErrorReason::Signalled). For
commands whose exit code is the answer — git diff --quiet, grep -q, …Source§fn checked<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<ProcessResult<String>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: Sync + 'async_trait,
fn checked<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<ProcessResult<String>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: Sync + 'async_trait,
Run, require an accepted exit (
0 by default, widened by
Command::ok_codes), and return the full
captured result (untrimmed stdout). The building block for the
parse/try_parse helpers — use it when you need the whole
ProcessResult after success-checking, rather than just trimmed stdout
(run) or the raw result (output_string). Read moreSource§fn parse<'life0, 'life1, 'async_trait, T, F>(
&'life0 self,
command: &'life1 Command,
parse: F,
) -> Pin<Box<dyn Future<Output = Result<T, Error>> + Send + 'async_trait>>
fn parse<'life0, 'life1, 'async_trait, T, F>( &'life0 self, command: &'life1 Command, parse: F, ) -> Pin<Box<dyn Future<Output = Result<T, Error>> + Send + 'async_trait>>
Run (requiring an accepted exit) and feed the captured stdout to an
infallible
parse closure — the shape of struct-returning CLI
commands (git/jj --format output). Built on checked,
but unlike it, fails loud on a bounded-buffer truncation so the
parser never silently sees a clipped tail; returns the parsed value. Read moreSource§fn try_parse<'life0, 'life1, 'async_trait, T, F>(
&'life0 self,
command: &'life1 Command,
parse: F,
) -> Pin<Box<dyn Future<Output = Result<T, Error>> + Send + 'async_trait>>
fn try_parse<'life0, 'life1, 'async_trait, T, F>( &'life0 self, command: &'life1 Command, parse: F, ) -> Pin<Box<dyn Future<Output = Result<T, Error>> + Send + 'async_trait>>
Run (requiring an accepted exit) and feed the captured stdout to a
fallible
parse closure — the shape of JSON deserialization, where a
parse failure becomes ErrorReason::Parse (or whatever
error the closure returns). Like parse it is built on
checked, fails loud on truncation, and — being generic
over F — cannot be dispatched through a dyn ProcessRunnerExt object
(the trait isn’t object-safe), though it is callable on a
&dyn ProcessRunner. The Command::try_parse /
CliClient::try_parse wrappers are the
ergonomic path.Source§fn first_line<'life0, 'life1, 'async_trait, F>(
&'life0 self,
command: &'life1 Command,
predicate: F,
) -> Pin<Box<dyn Future<Output = Result<Option<String>, Error>> + Send + 'async_trait>>
fn first_line<'life0, 'life1, 'async_trait, F>( &'life0 self, command: &'life1 Command, predicate: F, ) -> Pin<Box<dyn Future<Output = Result<Option<String>, Error>> + Send + 'async_trait>>
Stream
command’s stdout and return the first line matching predicate
(None if the stream ends first), bounded by the command’s
timeout: a Some deadline surfaces as
ErrorReason::Timeout and tears the process down. On an
own-group runner (JobRunner, the default) that teardown covers the
whole tree; on a shared ProcessGroup it reaches
the run’s direct child by pid — a forking child’s grandchildren (and, on the
Linux cgroup mechanism, a direct child that catches the graceful signal and
closes stdout but keeps running) may outlive the probe until the group is
dropped. Bound such a run with a whole-chain owner instead. Read more