Skip to main content

Diagnostics

Struct Diagnostics 

Source
pub struct Diagnostics<W> { /* private fields */ }
Expand description

A writer bound to one stream, safe to share.

Generic over the stream so a test can hand it a buffer and read the bytes back. In production that buffer is stderr, and Diagnostics::stderr is the only constructor that says so.

§Examples

use protocol_droid::adapters::primary::stdio::Diagnostics;

// The real channel: process stderr, and nothing else.
let diagnostics = Diagnostics::stderr();
diagnostics.write_all(b"listening on stdio\n").await?;

Implementations§

Source§

impl Diagnostics<Stderr>

Source

pub fn stderr() -> Self

The real diagnostics channel: this process’s stderr.

The only constructor that names a process stream, and the only one that can reach stdout — which it cannot, because it takes no argument to say so.

Source§

impl<W> Diagnostics<W>

Source

pub fn new(writer: W) -> Self

Binds the channel to a stream.

Public because a test needs it and a caller embedding this transport needs it; neither is a route to stdout by accident, since choosing the stream is the whole of what this function does.

Source§

impl<W> Diagnostics<W>
where W: AsyncWrite + Unpin,

Source

pub async fn write_all(&self, bytes: &[u8]) -> Result<(), StdioError>

Writes a diagnostic line, holding the lock for the whole write.

The lock spans the write rather than the frame boundary because a diagnostic interleaved with another diagnostic is a corrupted log, and a corrupted log is the failure mode that makes people turn logging off.

§Errors

StdioError::Transport when the underlying stream refuses the bytes. A diagnostic that cannot be written is never worth failing a request over, so callers that treat it as best-effort can discard this.

Source

pub async fn writer(&self) -> DiagnosticsWriter<'_, W>

Borrows the channel as a plain AsyncWrite, for a caller that already holds an AsyncWrite and would otherwise need a wrapper.

The borrow is the point, and it is why this is not an AsyncWrite impl on Diagnostics itself. The AsyncWrite methods take &mut self, so implementing the trait on the shared type would mean the channel could only ever be written by one task at a time and could not be shared at all — and a diagnostics channel that cannot be shared is not one. The returned guard holds the lock for as long as the caller keeps it, which makes write_all the same operation spelled differently rather than a different guarantee.

A guard is the borrow check made visible: it will not compile if the caller tries to reach the channel a second time while holding it, which is the mistake a shared AsyncWrite implementation would have hidden behind a lock.

Trait Implementations§

Source§

impl<W: Debug> Debug for Diagnostics<W>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<W> !Freeze for Diagnostics<W>

§

impl<W> !RefUnwindSafe for Diagnostics<W>

§

impl<W> Send for Diagnostics<W>
where Mutex<W>: Send,

§

impl<W> Sync for Diagnostics<W>
where Mutex<W>: Sync,

§

impl<W> Unpin for Diagnostics<W>
where Mutex<W>: Unpin,

§

impl<W> UnsafeUnpin for Diagnostics<W>
where Mutex<W>: UnsafeUnpin,

§

impl<W> UnwindSafe for Diagnostics<W>
where Mutex<W>: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more