Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add statistics. Move client stats from Monitor to EventManager #2940

Merged
merged 9 commits into from
Feb 6, 2025
8 changes: 6 additions & 2 deletions libafl/examples/tui_mock/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@

use std::{thread::sleep, time::Duration};

use libafl::monitors::{tui::TuiMonitor, ClientStats, Monitor};
use libafl::{
monitors::{tui::TuiMonitor, Monitor},
statistics::{manager::ClientStatsManager, ClientStats},
};
use libafl_bolts::ClientId;

pub fn main() {
Expand All @@ -14,7 +17,8 @@ pub fn main() {
executions: 512,
..ClientStats::default()
};
let mut client_stats_manager = ClientStatsManager::default();

monitor.display("Test", ClientId(0));
monitor.display(&mut client_stats_manager, "Test", ClientId(0));
sleep(Duration::from_secs(10));
}
2 changes: 1 addition & 1 deletion libafl/src/corpus/minimizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ use crate::{
events::{Event, EventFirer, LogSeverity},
executors::{Executor, HasObservers},
inputs::Input,
monitors::{AggregatorOps, UserStats, UserStatsValue},
observers::{MapObserver, ObserversTuple},
schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore},
state::{HasCorpus, HasExecutions},
statistics::user_stats::{AggregatorOps, UserStats, UserStatsValue},
Error, HasMetadata, HasScheduler,
};

Expand Down
59 changes: 34 additions & 25 deletions libafl/src/events/broker_hooks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::events::llmp::COMPRESS_THRESHOLD;
use crate::{
events::{llmp::LLMP_TAG_EVENT_TO_BOTH, BrokerEventResult, Event},
monitors::Monitor,
statistics::manager::ClientStatsManager,
Error,
};

Expand All @@ -37,6 +38,7 @@ pub struct StdLlmpEventHook<I, MT> {
#[cfg(feature = "llmp_compression")]
compressor: GzipCompressor,
phantom: PhantomData<I>,
client_stats_manager: ClientStatsManager,
}

impl<I, MT, SHM, SP> LlmpHook<SHM, SP> for StdLlmpEventHook<I, MT>
Expand Down Expand Up @@ -71,7 +73,12 @@ where
&*msg
};
let event: Event<I> = postcard::from_bytes(event_bytes)?;
match Self::handle_in_broker(monitor, client_id, &event)? {
match Self::handle_in_broker(
monitor,
&mut self.client_stats_manager,
client_id,
&event,
)? {
BrokerEventResult::Forward => Ok(LlmpMsgHookResult::ForwardToClients),
BrokerEventResult::Handled => Ok(LlmpMsgHookResult::Handled),
}
Expand All @@ -81,7 +88,11 @@ where
}

fn on_timeout(&mut self) -> Result<(), Error> {
self.monitor.display("Broker Heartbeat", ClientId(0));
self.monitor.display(
&mut self.client_stats_manager,
"Broker Heartbeat",
ClientId(0),
);
Ok(())
}
}
Expand All @@ -96,6 +107,7 @@ where
monitor,
#[cfg(feature = "llmp_compression")]
compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD),
client_stats_manager: ClientStatsManager::default(),
phantom: PhantomData,
})
}
Expand All @@ -104,6 +116,7 @@ where
#[expect(clippy::unnecessary_wraps)]
fn handle_in_broker(
monitor: &mut MT,
client_stats_manager: &mut ClientStatsManager,
client_id: ClientId,
event: &Event<I>,
) -> Result<BrokerEventResult, Error> {
Expand All @@ -119,11 +132,11 @@ where
client_id
};

monitor.client_stats_insert(id);
monitor.update_client_stats_for(id, |client_stat| {
client_stats_manager.client_stats_insert(id);
client_stats_manager.update_client_stats_for(id, |client_stat| {
client_stat.update_corpus_size(*corpus_size as u64);
});
monitor.display(event.name(), id);
monitor.display(client_stats_manager, event.name(), id);
Ok(BrokerEventResult::Forward)
}
Event::UpdateExecStats {
Expand All @@ -132,56 +145,52 @@ where
phantom: _,
} => {
// TODO: The monitor buffer should be added on client add.
monitor.client_stats_insert(client_id);
monitor.update_client_stats_for(client_id, |client_stat| {
client_stats_manager.client_stats_insert(client_id);
client_stats_manager.update_client_stats_for(client_id, |client_stat| {
client_stat.update_executions(*executions, *time);
});
monitor.display(event.name(), client_id);
monitor.display(client_stats_manager, event.name(), client_id);
Ok(BrokerEventResult::Handled)
}
Event::UpdateUserStats {
name,
value,
phantom: _,
} => {
monitor.client_stats_insert(client_id);
monitor.update_client_stats_for(client_id, |client_stat| {
Event::UpdateUserStats { name, value, .. } => {
client_stats_manager.client_stats_insert(client_id);
client_stats_manager.update_client_stats_for(client_id, |client_stat| {
client_stat.update_user_stats(name.clone(), value.clone());
});
monitor.aggregate(name);
monitor.display(event.name(), client_id);
client_stats_manager.aggregate(name);
monitor.display(client_stats_manager, event.name(), client_id);
Ok(BrokerEventResult::Handled)
}
#[cfg(feature = "introspection")]
Event::UpdatePerfMonitor {
time,
executions,
introspection_monitor,
introspection_stats,
phantom: _,
} => {
// TODO: The monitor buffer should be added on client add.

// Get the client for the staterestorer ID
monitor.client_stats_insert(client_id);
monitor.update_client_stats_for(client_id, |client_stat| {
client_stats_manager.client_stats_insert(client_id);
client_stats_manager.update_client_stats_for(client_id, |client_stat| {
// Update the normal monitor for this client
client_stat.update_executions(*executions, *time);
// Update the performance monitor for this client
client_stat.update_introspection_monitor((**introspection_monitor).clone());
client_stat.update_introspection_stats((**introspection_stats).clone());
});

// Display the monitor via `.display` only on core #1
monitor.display(event.name(), client_id);
monitor.display(client_stats_manager, event.name(), client_id);

// Correctly handled the event
Ok(BrokerEventResult::Handled)
}
Event::Objective { objective_size, .. } => {
monitor.client_stats_insert(client_id);
monitor.update_client_stats_for(client_id, |client_stat| {
client_stats_manager.client_stats_insert(client_id);
client_stats_manager.update_client_stats_for(client_id, |client_stat| {
client_stat.update_objective_size(*objective_size as u64);
});
monitor.display(event.name(), client_id);
monitor.display(client_stats_manager, event.name(), client_id);
Ok(BrokerEventResult::Handled)
}
Event::Log {
Expand Down
12 changes: 6 additions & 6 deletions libafl/src/events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ use uuid::Uuid;
use crate::{
executors::ExitKind,
inputs::Input,
monitors::UserStats,
state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor},
statistics::user_stats::UserStats,
Error, HasMetadata,
};

Expand Down Expand Up @@ -107,7 +107,7 @@ pub struct EventManagerId(
#[cfg(all(unix, feature = "std", feature = "multi_machine"))]
use crate::events::multi_machine::NodeId;
#[cfg(feature = "introspection")]
use crate::monitors::ClientPerfMonitor;
use crate::statistics::perf_stats::ClientPerfStats;
use crate::{observers::TimeObserver, stages::HasCurrentStageId};

/// The log event severity
Expand Down Expand Up @@ -294,7 +294,7 @@ pub enum Event<I> {
/// The executions of this client
executions: u64,
/// Current performance statistics
introspection_monitor: Box<ClientPerfMonitor>,
introspection_stats: Box<ClientPerfStats>,

/// phantomm data
phantom: PhantomData<I>,
Expand Down Expand Up @@ -514,17 +514,17 @@ where
#[cfg(feature = "introspection")]
{
state
.introspection_monitor_mut()
.introspection_stats_mut()
.set_current_time(libafl_bolts::cpu::read_time_counter());

// Send the current monitor over to the manager. This `.clone` shouldn't be
// costly as `ClientPerfMonitor` impls `Copy` since it only contains `u64`s
// costly as `ClientPerfStats` impls `Copy` since it only contains `u64`s
reporter.fire(
state,
Event::UpdatePerfMonitor {
executions,
time: cur,
introspection_monitor: Box::new(state.introspection_monitor().clone()),
introspection_stats: Box::new(state.introspection_stats().clone()),
phantom: PhantomData,
},
)?;
Expand Down
64 changes: 34 additions & 30 deletions libafl/src/events/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,11 @@ use crate::{
monitors::Monitor,
stages::HasCurrentStageId,
state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, Stoppable},
statistics::manager::ClientStatsManager,
Error, HasMetadata,
};
#[cfg(feature = "std")]
use crate::{
monitors::{ClientStats, SimplePrintingMonitor},
state::HasSolutions,
};
use crate::{monitors::SimplePrintingMonitor, state::HasSolutions, statistics::ClientStats};

/// The llmp connection from the actual fuzzer to the process supervising it
const _ENV_FUZZER_SENDER: &str = "_AFL_ENV_FUZZER_SENDER";
Expand All @@ -55,6 +53,7 @@ pub struct SimpleEventManager<I, MT, S> {
/// The events that happened since the last `handle_in_broker`
events: Vec<Event<I>>,
phantom: PhantomData<S>,
client_stats_manager: ClientStatsManager,
}

impl<I, MT, S> Debug for SimpleEventManager<I, MT, S>
Expand Down Expand Up @@ -84,7 +83,7 @@ where
}

fn fire(&mut self, _state: &mut S, event: Event<I>) -> Result<(), Error> {
match Self::handle_in_broker(&mut self.monitor, &event)? {
match Self::handle_in_broker(&mut self.monitor, &mut self.client_stats_manager, &event)? {
BrokerEventResult::Forward => self.events.push(event),
BrokerEventResult::Handled => (),
}
Expand Down Expand Up @@ -199,65 +198,70 @@ where
Self {
monitor,
events: vec![],
client_stats_manager: ClientStatsManager::default(),
phantom: PhantomData,
}
}

/// Handle arriving events in the broker
#[expect(clippy::unnecessary_wraps)]
fn handle_in_broker(monitor: &mut MT, event: &Event<I>) -> Result<BrokerEventResult, Error> {
fn handle_in_broker(
monitor: &mut MT,
client_stats_manager: &mut ClientStatsManager,
event: &Event<I>,
) -> Result<BrokerEventResult, Error> {
match event {
Event::NewTestcase { corpus_size, .. } => {
monitor.client_stats_insert(ClientId(0));
monitor.update_client_stats_for(ClientId(0), |client_stat| {
client_stats_manager.client_stats_insert(ClientId(0));
client_stats_manager.update_client_stats_for(ClientId(0), |client_stat| {
client_stat.update_corpus_size(*corpus_size as u64);
});
monitor.display(event.name(), ClientId(0));
monitor.display(client_stats_manager, event.name(), ClientId(0));
Ok(BrokerEventResult::Handled)
}
Event::UpdateExecStats {
time, executions, ..
} => {
// TODO: The monitor buffer should be added on client add.
monitor.client_stats_insert(ClientId(0));
monitor.update_client_stats_for(ClientId(0), |client_stat| {
client_stats_manager.client_stats_insert(ClientId(0));
client_stats_manager.update_client_stats_for(ClientId(0), |client_stat| {
client_stat.update_executions(*executions, *time);
});

monitor.display(event.name(), ClientId(0));
monitor.display(client_stats_manager, event.name(), ClientId(0));
Ok(BrokerEventResult::Handled)
}
Event::UpdateUserStats { name, value, .. } => {
monitor.client_stats_insert(ClientId(0));
monitor.update_client_stats_for(ClientId(0), |client_stat| {
client_stats_manager.client_stats_insert(ClientId(0));
client_stats_manager.update_client_stats_for(ClientId(0), |client_stat| {
client_stat.update_user_stats(name.clone(), value.clone());
});
monitor.aggregate(name);
monitor.display(event.name(), ClientId(0));
client_stats_manager.aggregate(name);
monitor.display(client_stats_manager, event.name(), ClientId(0));
Ok(BrokerEventResult::Handled)
}
#[cfg(feature = "introspection")]
Event::UpdatePerfMonitor {
time,
executions,
introspection_monitor,
introspection_stats,
..
} => {
// TODO: The monitor buffer should be added on client add.
monitor.client_stats_insert(ClientId(0));
monitor.update_client_stats_for(ClientId(0), |client_stat| {
client_stats_manager.client_stats_insert(ClientId(0));
client_stats_manager.update_client_stats_for(ClientId(0), |client_stat| {
client_stat.update_executions(*executions, *time);
client_stat.update_introspection_monitor((**introspection_monitor).clone());
client_stat.update_introspection_stats((**introspection_stats).clone());
});
monitor.display(event.name(), ClientId(0));
monitor.display(client_stats_manager, event.name(), ClientId(0));
Ok(BrokerEventResult::Handled)
}
Event::Objective { objective_size, .. } => {
monitor.client_stats_insert(ClientId(0));
monitor.update_client_stats_for(ClientId(0), |client_stat| {
client_stats_manager.client_stats_insert(ClientId(0));
client_stats_manager.update_client_stats_for(ClientId(0), |client_stat| {
client_stat.update_objective_size(*objective_size as u64);
});
monitor.display(event.name(), ClientId(0));
monitor.display(client_stats_manager, event.name(), ClientId(0));
Ok(BrokerEventResult::Handled)
}
Event::Log {
Expand Down Expand Up @@ -327,7 +331,7 @@ where
self.staterestorer.save(&(
state,
self.inner.monitor.start_time(),
self.inner.monitor.client_stats(),
self.inner.client_stats_manager.client_stats(),
))
}
}
Expand Down Expand Up @@ -543,12 +547,12 @@ where

// reload the state of the monitor to display the correct stats after restarts
monitor.set_start_time(start_time);
monitor.update_all_client_stats(clients_stats);
let mut this = SimpleRestartingEventManager::launched(monitor, staterestorer);
this.inner
.client_stats_manager
.update_all_client_stats(clients_stats);

(
Some(state),
SimpleRestartingEventManager::launched(monitor, staterestorer),
)
(Some(state), this)
}
};

Expand Down
Loading
Loading