AggRule

Enum AggRule 

Source
pub enum AggRule {
Show 14 variants SumCount(fn(&ThreadState) -> MonotonicCount), SumNs(fn(&ThreadState) -> MonotonicNs), SumTicks(fn(&ThreadState) -> ClockTicks), SumBytes(fn(&ThreadState) -> Bytes), MaxPeak(fn(&ThreadState) -> PeakNs), MaxPeakBytes(fn(&ThreadState) -> PeakBytes), MaxGaugeNs(fn(&ThreadState) -> GaugeNs), MaxGaugeCount(fn(&ThreadState) -> GaugeCount), RangeI32(fn(&ThreadState) -> OrdinalI32), RangeU32(fn(&ThreadState) -> OrdinalU32), Mode(fn(&ThreadState) -> CategoricalString), ModeChar(fn(&ThreadState) -> char), ModeBool(fn(&ThreadState) -> bool), Affinity(fn(&ThreadState) -> CpuSet),
}
Expand description

Aggregation rule for a single metric.

Encoded as an enum rather than a trait object so the registry table (CTPROF_METRICS) can live in static memory. Each variant’s accessor returns the typed crate::metric_types newtype that matches the reduction — the reader and rule are paired by construction so a new metric cannot register a peak field against a sum reducer (SumNs(|t| t.wait_max) fails to compile because wait_max is PeakNs, not MonotonicNs).

Each variant maps 1:1 to a marker trait in crate::metric_types: Sum* variants take a Summable type, Max* variants take a Maxable type that is NOT also Summable (counters use Sum* even though they implement both — registering a counter as Max* would mask the sum semantics with the per-contributor maximum), Range* variants take a Rangeable type, Mode* variants take a Modeable type or a primitive that the dispatch coerces to String, and AggRule::Affinity takes the dedicated crate::metric_types::CpuSet for the affinity-summary reduction.

Variants§

§

SumCount(fn(&ThreadState) -> MonotonicCount)

Sum across the group of a MonotonicCount field. Used for unitless cumulative counters (nr_wakeups, voluntary_csw, minflt, syscall counts, …). The dispatch routes through crate::metric_types::Summable::sum_across which uses saturating_add per the no-wraparound contract.

§

SumNs(fn(&ThreadState) -> MonotonicNs)

Sum across the group of a MonotonicNs field. Used for cumulative-time counters in nanoseconds (run_time_ns, wait_time_ns, wait_sum, voluntary_sleep_ns, block_sum, iowait_sum, core_forceidle_sum).

§

SumTicks(fn(&ThreadState) -> ClockTicks)

Sum across the group of a ClockTicks field. Used for USER_HZ-scaled cumulative time counters (utime_clock_ticks, stime_clock_ticks).

§

SumBytes(fn(&ThreadState) -> Bytes)

Sum across the group of a Bytes field. Used for IEC-binary-scaled byte counters (allocated_bytes, deallocated_bytes, rchar, wchar, read_bytes, write_bytes, cancelled_write_bytes).

§

MaxPeak(fn(&ThreadState) -> PeakNs)

Maximum across the group of a PeakNs field — the kernel *_max schedstats (wait_max, sleep_max, block_max, exec_max, slice_max). Each thread already carries its own lifetime max-seen value from the kernel’s scheduler call sites (e.g. update_se in kernel/sched/fair.c for exec_max; see struct sched_statistics in include/linux/sched.h). Group-level reduction takes the largest across members so a row surfaces the worst single window any thread in the group has ever experienced. Summing per-thread maxes would conflate “one thread with a 1s spike” with “1000 threads with 1ms spikes each” — PeakNs therefore does NOT implement Summable, and trying to register one as SumNs is a compile error.

§

MaxPeakBytes(fn(&ThreadState) -> PeakBytes)

Maximum across the group of a PeakBytes field — the byte-typed twin of MaxPeak. Used for taskstats-sourced lifetime memory watermarks (hiwater_rss_bytes, hiwater_vm_bytes). xacct_add_tsk (kernel/tsacct.c::xacct_add_tsk, lines 99-104) reads the watermark out of the SHARED mm_struct via get_mm_hiwater_rss(mm) / get_mm_hiwater_vm(mm), so sibling threads of the same tgid all report the same value; cross-thread Max within a single process is a no-op. Cross-PROCESS Max (e.g. under --group-by pcomm when the bucket spans multiple parent processes) is the meaningful reduction: it picks the largest watermark any tgid in the bucket reported. Routes through the IEC binary auto-scale ladder (crate::metric_types::ScaleLadder::Bytes) so a 7.5 GiB watermark renders as 7.500GiB instead of dominating the table with raw byte counts. Summing watermarks would over-count shared address-space mappings across sibling threads N-fold — PeakBytes does NOT implement Summable.

§

MaxGaugeNs(fn(&ThreadState) -> GaugeNs)

Maximum across the group of a GaugeNs field — instantaneous-time gauges where summing is meaningless. fair_slice_ns is the per-thread CURRENT scheduler slice (stale under SCHED_EXT — see field doc) read at capture time, not a high-water value. Summing instantaneous gauges produces a number with no physical meaning — N nearly-identical instantaneous values sum to N * gauge regardless of group composition, drowning the signal. Max instead surfaces “the longest current slice any thread in the bucket is running with”, which IS the signal a user comparing two snapshots cares about.

§

MaxGaugeCount(fn(&ThreadState) -> GaugeCount)

Maximum across the group of a GaugeCount field — leader-deduped structural counts. nr_threads is populated only on the tgid leader (tid == tgid) and zero on every non-leader thread of the same process; see capture_thread_at_with_tally. Sum across a comm- or cgroup-bucketed group would render 0 for any bucket whose leader fell elsewhere because non-leader members each contribute 0. Max instead reads through to the leader’s value, surfacing “the largest process represented in this bucket” regardless of which axis the bucket is built around. The row count already covers “how many threads are here”, so the structural field’s value adds new information rather than restating the row count.

§

RangeI32(fn(&ThreadState) -> OrdinalI32)

Ordinal i32, aggregated as the observed [min, max] range. Used for signed-domain ordinals (nice, priority, processor). Delta math uses the midpoint of each range as the scalar; output prints both the range and the delta. The dispatch routes through crate::metric_types::Rangeable::range_across and widens to i64 for Aggregated::OrdinalRange.

§

RangeU32(fn(&ThreadState) -> OrdinalU32)

Ordinal u32, aggregated as the observed [min, max] range. Used for unsigned-domain ordinals (rt_priority, kernel-typed unsigned int). Same shape as AggRule::RangeI32 but the inner width matches the kernel-side unsigned int declaration; the dispatch widens the resulting u32 to i64 for Aggregated::OrdinalRange.

§

Mode(fn(&ThreadState) -> CategoricalString)

Categorical string, aggregated as the mode (most-frequent value). Used for policy (string-valued crate::metric_types::CategoricalString). Delta is textual: “same” if both modes agree, “differs” otherwise — there is no arithmetic on a policy name. The dispatch routes through crate::metric_types::Modeable::mode_across.

§

ModeChar(fn(&ThreadState) -> char)

Categorical char, aggregated as the mode. Used for state (single-letter task state from /proc/<tid>/status). The dispatch coerces the char to a String via to_string() before reducing — char itself is NOT Modeable (only crate::metric_types::CategoricalString is), so this variant exists to keep the registry’s accessor type matching the ThreadState field type without forcing the field into a wrapper. If a second char-valued metric appears, promote both fields to a dedicated CategoricalChar wrapper rather than continuing the ad-hoc coercion (mirrors the CategoricalBool promotion guidance on AggRule::ModeBool).

§

ModeBool(fn(&ThreadState) -> bool)

Categorical bool, aggregated as the mode. Used for ext_enabled (sched_ext class membership). Same shape as AggRule::ModeChar: the dispatch coerces via to_string() so "true"/"false" participate in the mode reduction. If a second bool-valued metric appears, promote both fields to a dedicated CategoricalBool wrapper rather than continuing the ad-hoc coercion.

Tiebreak skew (FA-2): the lex-smallest-wins tiebreak inside Modeable::mode_across makes "false" ('f', 0x66) win an equal-count tie against "true" ('t', 0x74). This matches the legacy pre-phase-3 behavior — the old to_string() coercion fed the same string pair through the same lex-tiebreak — but is worth flagging explicitly: a 50/50 sched_ext-on/off bucket renders false as the mode rather than picking the more “informative” true. Operators reading a false mode in a heterogeneous bucket should check the count/total fraction.

§

Affinity(fn(&ThreadState) -> CpuSet)

CPU affinity set, aggregated as the num_cpus range across the group plus a uniform-cpuset rendering when every thread shared the same allowed set. Used for cpu_affinity. The accessor returns crate::metric_types::CpuSet; the dispatch unwraps to Vec<u32> for the AffinitySummary reduction.

Unlike the Sum* / Max* / Range* / Mode* rules, Affinity does NOT route through a crate::metric_types trait method — its reduction produces an AffinitySummary (num_cpus range + uniform-cpuset flag), not a homogeneous CpuSet, so the inline aggregator in aggregate walks the per-thread Vec<u32> directly. A future Affinable trait could fold the body into crate::metric_types but the summary type is single-use today.

Type-system bypass caveat (FA-1): the typed AggRule shape catches “wrong wrapper” mistakes (SumNs(|t| t.wait_max) fails to compile because wait_max is PeakNs), but a closure body that actively MISWRAPS the underlying field — e.g. SumNs(|t| MonotonicNs(t.wait_max.0)) — laundering a peak through the sum wrapper still type-checks. Don’t do that. The wrapper category is load-bearing; the type system catches the variant mismatch but cannot inspect the inside of an arbitrary closure.

Implementations§

Source§

impl AggRule

Source

pub fn ladder(&self) -> ScaleLadder

The auto-scale ladder for this rule’s value cell.

Closed match — adding a new AggRule variant requires adding the ladder mapping here. The mapping is one-to-one with the typed accessor newtype: AggRule::SumNsScaleLadder::Ns, AggRule::SumBytesScaleLadder::Bytes, etc.

Trait Implementations§

Source§

impl Clone for AggRule

Source§

fn clone(&self) -> AggRule

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for AggRule

Source§

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

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

impl Copy for AggRule

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

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

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: 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
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: 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> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

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
§

impl<T> MaybeSend for T
where T: Send,

§

impl<T> MaybeSend for T
where T: Send,