Skip to main content

Sampler

Struct Sampler 

Source
pub struct Sampler(/* private fields */);
Expand description

How often a warning a peer can repeat at will is allowed to be loud.

The rules above bound what one line may carry. This bounds how many lines there are, which is the other half of the same problem and the one an operator feels first: journald rate limiting counts lines, per unit, so a peer that can buy one warning per request does not merely fill a disk — it spends this service’s whole allowance and the genuine lines that follow are dropped. Suppressing the real signal is the more expensive half of the attack, and a peer needs no privilege to run it: a refusal is a request that went nowhere, so the refusals are the cheapest lines there are.

Silencing the repeats is not the answer either. The two warnings this guards are read as evidence — a client probing the private side of the host, a client sitting on its tunnel limit — and evidence that reports “it happened” while hiding “it happened sixty thousand times” is worse than useless.

So the schedule doubles: occurrence 1 is reported, then 2, 4, 8, and so on, each carrying the running total. A scan of every port on a host is 17 lines instead of 65535, the first of them lands as immediately as it does today, and the last one says it was 65536 — which is more than the unsampled version ever told anybody, since counting identical lines was left to whoever read the journal. The cost is that the count between reports is only known to within a factor of two until the next one arrives.

One of these per connection, so a peer cannot use a quiet neighbour’s allowance, and nothing here is ever reset: the schedule is about a connection’s whole life.

Implementations§

Source§

impl Sampler

Source

pub const fn new() -> Self

A sampler that has seen nothing yet.

Source

pub fn record(&self) -> Option<u64>

Records an occurrence: Some(total) when this one is to be reported.

Relaxed because the only thing ordered against is the counter itself — two threads racing here get two distinct totals and at most one of them is a power of two, which is all the schedule asks. Wrapping is unreachable (a u64 of refusals is longer than the hardware lasts) and harmless if it happened: zero is not a power of two, so the pass is quiet rather than wrong.

Trait Implementations§

Source§

impl Debug for Sampler

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Default for Sampler

Source§

fn default() -> Sampler

Returns the “default value” for a type. Read more

Auto Trait Implementations§

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<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

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

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

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, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.
§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self>

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