Move statistics to monitors/stats (#2962)

* Move statistics back to monitors/stats

* More fun

* more stats

* more
This commit is contained in:
Dominik Maier 2025-02-11 01:07:17 +01:00 committed by GitHub
parent e5ae6c361f
commit c62c6a7ecc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 67 additions and 222 deletions

View File

@ -1,4 +1,5 @@
# 0.15.0 -> 0.16.0 # 0.15.0 -> 0.16.0
- `EventManager` is refactored to avoid calling function from `Fuzzer`, thus we do not evaluate testcases in `EventManager` anymore. - `EventManager` is refactored to avoid calling function from `Fuzzer`, thus we do not evaluate testcases in `EventManager` anymore.
- Now we have `EventReceiver` in `events` module, and `EventProessor` in `fuzzer` module. - Now we have `EventReceiver` in `events` module, and `EventProessor` in `fuzzer` module.
- `EventReceiver` is responsible for receiving testcases and delegates its evaluation to `EventProcessor`. - `EventReceiver` is responsible for receiving testcases and delegates its evaluation to `EventProcessor`.
@ -6,13 +7,13 @@
- Since we don't evaluate testcases in the `EventManager` anymore. `on_fire` and `post_exec` have been deleted from `EventManagerHook`. - Since we don't evaluate testcases in the `EventManager` anymore. `on_fire` and `post_exec` have been deleted from `EventManagerHook`.
- Similarly `pre_exec` has been renamed to `pre_receive`. - Similarly `pre_exec` has been renamed to `pre_receive`.
- `AsanModule` now uses a `builder()` method for constructing its instances. - `AsanModule` now uses a `builder()` method for constructing its instances.
- `Monitor` is refactored. Most statistics have been extracted into an individual module `statistics` at crate root, and `Monitor` is kept as display only. - `Monitor` is refactored. Most statistics have been extracted into an individual `stats` module under `monitors`.
- There is a `ClientStatsManager` to manage client statistics, and is owned by `EventManager`. Most of previous `Monitor`'s trait methods have been moved to the `ClientStatsManager`. - There is a `ClientStatsManager` to manage client statistics, and is owned by `EventManager`. Most of previous `Monitor`'s trait methods have been moved to the `ClientStatsManager`.
- `user_monitor` has been renamed to `user_stats`, and its structure definitions have been moved to `statistics` module as well. - `user_monitor` has been renamed to `user_stats`, `introspection_monitor` has been renamed to `introspection_stats`, perf-related structure definitions have been renamed, and all were moved to the `stats` module.
- `introspection_monitor` has been renamed to `introspection_stats`, and perf-related structure definitions have been renamed and moved to `statistics` module as well.
- `OnDiskTomlMonitor`, `OnDiskJsonMonitor`, `OnDiskJsonAggregateMonitor` are now no longer takes a base monitor to wrap. If you want to use multiple monitors together, use `libafl::combine_monitor!`. - `OnDiskTomlMonitor`, `OnDiskJsonMonitor`, `OnDiskJsonAggregateMonitor` are now no longer takes a base monitor to wrap. If you want to use multiple monitors together, use `libafl::combine_monitor!`.
# 0.14.1 -> 0.15.0 # 0.14.1 -> 0.15.0
- `MmapShMem::new` and `MmapShMemProvider::new_shmem_with_id` now take `AsRef<Path>` instead of a byte array for the filename/id. - `MmapShMem::new` and `MmapShMemProvider::new_shmem_with_id` now take `AsRef<Path>` instead of a byte array for the filename/id.
- The closure passed to a `DumpToDiskStage` now provides the `Testcase` instead of just the `Input`. - The closure passed to a `DumpToDiskStage` now provides the `Testcase` instead of just the `Input`.
- `StatsStage` is deleted, and it is superceded by `AflStatsStage` - `StatsStage` is deleted, and it is superceded by `AflStatsStage`
@ -35,8 +36,10 @@
- Related: removed `hash_simple` from `MapObserver` - Related: removed `hash_simple` from `MapObserver`
# 0.14.0 -> 0.15.0 # 0.14.0 -> 0.15.0
- Removed `with_observers` from `Executor` trait. - Removed `with_observers` from `Executor` trait.
- `MmapShMemProvider::new_shmem_persistent` has been removed in favour of `MmapShMem::persist`. You probably want to do something like this: `let shmem = MmapShMemProvider::new()?.new_shmem(size)?.persist()?;` - `MmapShMemProvider::new_shmem_persistent` has been removed in favour of `MmapShMem::persist`. You probably want to do something like this: `let shmem = MmapShMemProvider::new()?.new_shmem(size)?.persist()?;`
# Pre 0.9 -> 0.9 # Pre 0.9 -> 0.9
- [Migrating from LibAFL <0.9 to 0.9](https://aflplus.plus/libafl-book/design/migration-0.9.html) - [Migrating from LibAFL <0.9 to 0.9](https://aflplus.plus/libafl-book/design/migration-0.9.html)

View File

@ -3,9 +3,10 @@
use std::{thread::sleep, time::Duration}; use std::{thread::sleep, time::Duration};
use libafl::{ use libafl::monitors::{
monitors::{tui::TuiMonitor, Monitor}, stats::{manager::ClientStatsManager, ClientStats},
statistics::{manager::ClientStatsManager, ClientStats}, tui::TuiMonitor,
Monitor,
}; };
use libafl_bolts::ClientId; use libafl_bolts::ClientId;

View File

@ -18,10 +18,10 @@ use crate::{
events::{Event, EventFirer, LogSeverity}, events::{Event, EventFirer, LogSeverity},
executors::{Executor, HasObservers}, executors::{Executor, HasObservers},
inputs::Input, inputs::Input,
monitors::stats::{AggregatorOps, UserStats, UserStatsValue},
observers::{MapObserver, ObserversTuple}, observers::{MapObserver, ObserversTuple},
schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore}, schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore},
state::{HasCorpus, HasExecutions}, state::{HasCorpus, HasExecutions},
statistics::user_stats::{AggregatorOps, UserStats, UserStatsValue},
Error, HasMetadata, HasScheduler, Error, HasMetadata, HasScheduler,
}; };

View File

@ -14,8 +14,7 @@ use serde::de::DeserializeOwned;
use crate::events::llmp::COMPRESS_THRESHOLD; use crate::events::llmp::COMPRESS_THRESHOLD;
use crate::{ use crate::{
events::{llmp::LLMP_TAG_EVENT_TO_BOTH, BrokerEventResult, Event}, events::{llmp::LLMP_TAG_EVENT_TO_BOTH, BrokerEventResult, Event},
monitors::Monitor, monitors::{stats::ClientStatsManager, Monitor},
statistics::manager::ClientStatsManager,
Error, Error,
}; };

View File

@ -47,8 +47,8 @@ use uuid::Uuid;
use crate::{ use crate::{
executors::ExitKind, executors::ExitKind,
inputs::Input, inputs::Input,
monitors::stats::UserStats,
state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor}, state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor},
statistics::user_stats::UserStats,
Error, HasMetadata, Error, HasMetadata,
}; };
@ -107,7 +107,7 @@ pub struct EventManagerId(
#[cfg(all(unix, feature = "std", feature = "multi_machine"))] #[cfg(all(unix, feature = "std", feature = "multi_machine"))]
use crate::events::multi_machine::NodeId; use crate::events::multi_machine::NodeId;
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
use crate::statistics::perf_stats::ClientPerfStats; use crate::monitors::stats::ClientPerfStats;
use crate::{observers::TimeObserver, stages::HasCurrentStageId}; use crate::{observers::TimeObserver, stages::HasCurrentStageId};
/// The log event severity /// The log event severity

View File

@ -31,14 +31,16 @@ use crate::{
Event, EventFirer, EventManagerId, EventReceiver, EventRestarter, HasEventManagerId, Event, EventFirer, EventManagerId, EventReceiver, EventRestarter, HasEventManagerId,
SendExiting, SendExiting,
}, },
monitors::Monitor, monitors::{stats::ClientStatsManager, Monitor},
stages::HasCurrentStageId, stages::HasCurrentStageId,
state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, Stoppable}, state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, Stoppable},
statistics::manager::ClientStatsManager,
Error, HasMetadata, Error, HasMetadata,
}; };
#[cfg(feature = "std")] #[cfg(feature = "std")]
use crate::{monitors::SimplePrintingMonitor, state::HasSolutions, statistics::ClientStats}; use crate::{
monitors::{stats::ClientStats, SimplePrintingMonitor},
state::HasSolutions,
};
/// The llmp connection from the actual fuzzer to the process supervising it /// The llmp connection from the actual fuzzer to the process supervising it
const _ENV_FUZZER_SENDER: &str = "_AFL_ENV_FUZZER_SENDER"; const _ENV_FUZZER_SENDER: &str = "_AFL_ENV_FUZZER_SENDER";

View File

@ -47,13 +47,12 @@ use crate::{
EventManagerId, EventReceiver, EventRestarter, HasEventManagerId, ProgressReporter, EventManagerId, EventReceiver, EventRestarter, HasEventManagerId, ProgressReporter,
}, },
inputs::Input, inputs::Input,
monitors::Monitor, monitors::{stats::ClientStatsManager, Monitor},
stages::HasCurrentStageId, stages::HasCurrentStageId,
state::{ state::{
HasCurrentTestcase, HasExecutions, HasImported, HasLastReportTime, HasSolutions, HasCurrentTestcase, HasExecutions, HasImported, HasLastReportTime, HasSolutions,
MaybeHasClientPerfMonitor, Stoppable, MaybeHasClientPerfMonitor, Stoppable,
}, },
statistics::manager::ClientStatsManager,
Error, HasMetadata, Error, HasMetadata,
}; };

View File

@ -25,8 +25,8 @@ use crate::{
events::{Event, EventFirer}, events::{Event, EventFirer},
executors::ExitKind, executors::ExitKind,
feedbacks::{Feedback, HasObserverHandle, StateInitializer}, feedbacks::{Feedback, HasObserverHandle, StateInitializer},
monitors::stats::{AggregatorOps, UserStats, UserStatsValue},
observers::{CanTrack, MapObserver}, observers::{CanTrack, MapObserver},
statistics::user_stats::{AggregatorOps, UserStats, UserStatsValue},
Error, HasMetadata, HasNamedMetadata, Error, HasMetadata, HasNamedMetadata,
}; };

View File

@ -11,7 +11,7 @@ use libafl_bolts::{current_time, tuples::MatchName};
use serde::{de::DeserializeOwned, Serialize}; use serde::{de::DeserializeOwned, Serialize};
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
use crate::statistics::perf_stats::PerfFeature; use crate::monitors::stats::PerfFeature;
use crate::{ use crate::{
corpus::{Corpus, CorpusId, HasCurrentCorpusId, HasTestcase, Testcase}, corpus::{Corpus, CorpusId, HasCurrentCorpusId, HasTestcase, Testcase},
events::{ events::{

View File

@ -79,7 +79,6 @@ pub mod observers;
pub mod schedulers; pub mod schedulers;
pub mod stages; pub mod stages;
pub mod state; pub mod state;
pub mod statistics;
pub use fuzzer::*; pub use fuzzer::*;
pub use libafl_bolts::{nonzero, Error}; pub use libafl_bolts::{nonzero, Error};
@ -91,8 +90,7 @@ pub mod prelude {
pub use super::{ pub use super::{
corpus::*, events::*, executors::*, feedbacks::*, fuzzer::*, generators::*, inputs::*, corpus::*, events::*, executors::*, feedbacks::*, fuzzer::*, generators::*, inputs::*,
monitors::*, mutators::*, observers::*, schedulers::*, stages::*, state::*, statistics::*, monitors::*, mutators::*, observers::*, schedulers::*, stages::*, state::*, *,
*,
}; };
} }

View File

@ -11,7 +11,7 @@ use std::{
use libafl_bolts::{current_time, ClientId}; use libafl_bolts::{current_time, ClientId};
use serde_json::json; use serde_json::json;
use crate::{monitors::Monitor, statistics::manager::ClientStatsManager}; use crate::monitors::{stats::ClientStatsManager, Monitor};
/// Wrap a monitor and log the current state of the monitor into a Toml file. /// Wrap a monitor and log the current state of the monitor into a Toml file.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View File

@ -9,7 +9,7 @@ use std::{fs::OpenOptions, io::Write, path::PathBuf};
use libafl_bolts::{current_time, ClientId}; use libafl_bolts::{current_time, ClientId};
use serde_json::json; use serde_json::json;
use crate::{monitors::Monitor, statistics::manager::ClientStatsManager}; use crate::monitors::{stats::ClientStatsManager, Monitor};
/// A monitor that logs aggregated stats to a JSON file. /// A monitor that logs aggregated stats to a JSON file.
#[derive(Clone)] #[derive(Clone)]

View File

@ -3,6 +3,8 @@
pub mod multi; pub mod multi;
pub use multi::MultiMonitor; pub use multi::MultiMonitor;
pub mod stats;
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub mod disk; pub mod disk;
#[cfg(feature = "std")] #[cfg(feature = "std")]
@ -30,7 +32,7 @@ use libafl_bolts::ClientId;
#[cfg(all(feature = "prometheus_monitor", feature = "std"))] #[cfg(all(feature = "prometheus_monitor", feature = "std"))]
pub use prometheus::PrometheusMonitor; pub use prometheus::PrometheusMonitor;
use crate::statistics::manager::ClientStatsManager; use crate::monitors::stats::ClientStatsManager;
/// The monitor trait keeps track of all the client's monitor, and offers methods to display them. /// The monitor trait keeps track of all the client's monitor, and offers methods to display them.
pub trait Monitor { pub trait Monitor {

View File

@ -8,7 +8,7 @@ use core::{
use libafl_bolts::{current_time, ClientId}; use libafl_bolts::{current_time, ClientId};
use crate::{monitors::Monitor, statistics::manager::ClientStatsManager}; use crate::monitors::{stats::ClientStatsManager, Monitor};
/// Tracking monitor during fuzzing and display both per-client and cumulative info. /// Tracking monitor during fuzzing and display both per-client and cumulative info.
#[derive(Clone)] #[derive(Clone)]

View File

@ -47,9 +47,9 @@ use prometheus_client::{
// using tide for the HTTP server library (fast, async, simple) // using tide for the HTTP server library (fast, async, simple)
use tide::Request; use tide::Request;
use crate::{ use crate::monitors::{
monitors::Monitor, stats::{manager::ClientStatsManager, user_stats::UserStatsValue},
statistics::{manager::ClientStatsManager, user_stats::UserStatsValue}, Monitor,
}; };
/// Prometheus metrics for global and each client. /// Prometheus metrics for global and each client.

View File

@ -13,12 +13,13 @@ use core::time::Duration;
use hashbrown::HashMap; use hashbrown::HashMap;
use libafl_bolts::current_time; use libafl_bolts::current_time;
pub use manager::ClientStatsManager;
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
use perf_stats::ClientPerfStats; pub use perf_stats::{ClientPerfStats, PerfFeature};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use serde_json::Value; use serde_json::Value;
use user_stats::UserStats; pub use user_stats::{AggregatorOps, UserStats, UserStatsValue};
#[cfg(feature = "afl_exec_sec")] #[cfg(feature = "afl_exec_sec")]
const CLIENT_STATS_TIME_WINDOW_SECS: u64 = 5; // 5 seconds const CLIENT_STATS_TIME_WINDOW_SECS: u64 = 5; // 5 seconds
@ -107,13 +108,17 @@ impl ProcessTiming {
} }
/// The geometry of a single data point /// The geometry of a single data point
#[expect(missing_docs)]
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct ItemGeometry { pub struct ItemGeometry {
/// Pending entries
pub pending: u64, pub pending: u64,
/// Favored pending entries
pub pend_fav: u64, pub pend_fav: u64,
/// How much entries we found
pub own_finds: u64, pub own_finds: u64,
/// How much entries were imported
pub imported: u64, pub imported: u64,
/// The stability, stringified
pub stability: String, pub stability: String,
} }

View File

@ -147,7 +147,7 @@ impl fmt::Display for UserStatsValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self { match &self {
UserStatsValue::Number(n) => write!(f, "{n}"), UserStatsValue::Number(n) => write!(f, "{n}"),
UserStatsValue::Float(n) => write!(f, "{}", crate::statistics::prettify_float(*n)), UserStatsValue::Float(n) => write!(f, "{}", crate::monitors::stats::prettify_float(*n)),
UserStatsValue::Percent(n) => write!(f, "{:.3}%", n * 100.0), UserStatsValue::Percent(n) => write!(f, "{:.3}%", n * 100.0),
UserStatsValue::String(s) => write!(f, "{s}"), UserStatsValue::String(s) => write!(f, "{s}"),
UserStatsValue::Ratio(a, b) => { UserStatsValue::Ratio(a, b) => {

View File

@ -27,13 +27,13 @@ use ratatui::{backend::CrosstermBackend, Terminal};
use typed_builder::TypedBuilder; use typed_builder::TypedBuilder;
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
use crate::statistics::perf_stats::{ClientPerfStats, PerfFeature}; use crate::monitors::stats::perf_stats::{ClientPerfStats, PerfFeature};
use crate::{ use crate::monitors::{
monitors::Monitor, stats::{
statistics::{
manager::ClientStatsManager, user_stats::UserStats, ClientStats, ItemGeometry, manager::ClientStatsManager, user_stats::UserStats, ClientStats, ItemGeometry,
ProcessTiming, ProcessTiming,
}, },
Monitor,
}; };
#[expect(missing_docs)] #[expect(missing_docs)]
@ -207,19 +207,26 @@ impl PerfTuiContext {
} }
/// The context for a single client tracked in this [`TuiMonitor`] /// The context for a single client tracked in this [`TuiMonitor`]
#[expect(missing_docs)]
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct ClientTuiContext { pub struct ClientTuiContext {
/// The corpus size
pub corpus: u64, pub corpus: u64,
/// Amount of objectives
pub objectives: u64, pub objectives: u64,
/// Amount of executions
pub executions: u64, pub executions: u64,
/// Float value formatted as String /// Float value formatted as String
pub map_density: String, pub map_density: String,
/// How many cycles have been done.
/// Roughly: every testcase has been scheduled once, but highly fuzzer-specific.
pub cycles_done: u64, pub cycles_done: u64,
/// Times for processing
pub process_timing: ProcessTiming, pub process_timing: ProcessTiming,
/// The individual entry geometry
pub item_geometry: ItemGeometry, pub item_geometry: ItemGeometry,
/// Extra fuzzer-specific stats
pub user_stats: HashMap<Cow<'static, str>, UserStats>, pub user_stats: HashMap<Cow<'static, str>, UserStats>,
} }
@ -241,8 +248,8 @@ impl ClientTuiContext {
} }
/// The [`TuiContext`] for this [`TuiMonitor`] /// The [`TuiContext`] for this [`TuiMonitor`]
#[expect(missing_docs)]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[expect(missing_docs)]
pub struct TuiContext { pub struct TuiContext {
pub graphs: Vec<String>, pub graphs: Vec<String>,

View File

@ -1,3 +1,4 @@
//! The UI-specific parts of [`super::TuiMonitor`]
use alloc::{string::ToString, vec::Vec}; use alloc::{string::ToString, vec::Vec};
use std::{ use std::{
cmp::{max, min}, cmp::{max, min},
@ -93,6 +94,7 @@ impl TuiUi {
} }
} }
/// Draw the current TUI context
pub fn draw(&mut self, f: &mut Frame, app: &Arc<RwLock<TuiContext>>) { pub fn draw(&mut self, f: &mut Frame, app: &Arc<RwLock<TuiContext>>) {
self.clients = app.read().unwrap().clients_num; self.clients = app.read().unwrap().clients_num;

View File

@ -26,12 +26,12 @@ use crate::{
corpus::{Corpus, HasCurrentCorpusId, SchedulerTestcaseMetadata, Testcase}, corpus::{Corpus, HasCurrentCorpusId, SchedulerTestcaseMetadata, Testcase},
events::{Event, EventFirer}, events::{Event, EventFirer},
executors::HasObservers, executors::HasObservers,
monitors::stats::{AggregatorOps, UserStats, UserStatsValue},
mutators::Tokens, mutators::Tokens,
observers::MapObserver, observers::MapObserver,
schedulers::{minimizer::IsFavoredMetadata, HasQueueCycles}, schedulers::{minimizer::IsFavoredMetadata, HasQueueCycles},
stages::{calibrate::UnstableEntriesMetadata, Stage}, stages::{calibrate::UnstableEntriesMetadata, Stage},
state::{HasCorpus, HasExecutions, HasImported, HasStartTime, Stoppable}, state::{HasCorpus, HasExecutions, HasImported, HasStartTime, Stoppable},
statistics::user_stats::{AggregatorOps, UserStats, UserStatsValue},
std::string::ToString, std::string::ToString,
Error, HasMetadata, HasNamedMetadata, HasScheduler, Error, HasMetadata, HasNamedMetadata, HasScheduler,
}; };

View File

@ -19,11 +19,11 @@ use crate::{
feedbacks::{map::MapFeedbackMetadata, HasObserverHandle}, feedbacks::{map::MapFeedbackMetadata, HasObserverHandle},
fuzzer::Evaluator, fuzzer::Evaluator,
inputs::Input, inputs::Input,
monitors::stats::{AggregatorOps, UserStats, UserStatsValue},
observers::{MapObserver, ObserversTuple}, observers::{MapObserver, ObserversTuple},
schedulers::powersched::SchedulerMetadata, schedulers::powersched::SchedulerMetadata,
stages::{RetryCountRestartHelper, Stage}, stages::{RetryCountRestartHelper, Stage},
state::{HasCorpus, HasCurrentTestcase, HasExecutions}, state::{HasCorpus, HasCurrentTestcase, HasExecutions},
statistics::user_stats::{AggregatorOps, UserStats, UserStatsValue},
Error, HasMetadata, HasNamedMetadata, Error, HasMetadata, HasNamedMetadata,
}; };

View File

@ -13,7 +13,7 @@ use libafl_bolts::{
}; };
#[cfg(all(feature = "concolic_mutation", feature = "introspection"))] #[cfg(all(feature = "concolic_mutation", feature = "introspection"))]
use crate::statistics::perf_stats::PerfFeature; use crate::monitors::stats::PerfFeature;
use crate::{ use crate::{
corpus::HasCurrentCorpusId, corpus::HasCurrentCorpusId,
executors::{Executor, HasObservers}, executors::{Executor, HasObservers},

View File

@ -12,7 +12,7 @@ use libafl_bolts::{
}; };
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
use crate::statistics::perf_stats::PerfFeature; use crate::monitors::stats::PerfFeature;
use crate::{ use crate::{
corpus::{Corpus, HasCurrentCorpusId}, corpus::{Corpus, HasCurrentCorpusId},
executors::{Executor, HasObservers}, executors::{Executor, HasObservers},

View File

@ -10,7 +10,7 @@ use core::{marker::PhantomData, num::NonZeroUsize};
use libafl_bolts::{rands::Rand, Named}; use libafl_bolts::{rands::Rand, Named};
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
use crate::statistics::perf_stats::PerfFeature; use crate::monitors::stats::PerfFeature;
use crate::{ use crate::{
corpus::{Corpus, CorpusId, HasCurrentCorpusId, Testcase}, corpus::{Corpus, CorpusId, HasCurrentCorpusId, Testcase},
fuzzer::Evaluator, fuzzer::Evaluator,

View File

@ -9,7 +9,7 @@ use core::{fmt::Debug, marker::PhantomData};
use libafl_bolts::Named; use libafl_bolts::Named;
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
use crate::statistics::perf_stats::PerfFeature; use crate::monitors::stats::PerfFeature;
use crate::{ use crate::{
corpus::HasCurrentCorpusId, corpus::HasCurrentCorpusId,
executors::{Executor, HasObservers}, executors::{Executor, HasObservers},

View File

@ -12,7 +12,7 @@ use serde::Serialize;
use super::{PushStage, PushStageHelper, PushStageSharedState}; use super::{PushStage, PushStageHelper, PushStageSharedState};
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
use crate::statistics::perf_stats::PerfFeature; use crate::monitors::stats::PerfFeature;
use crate::{ use crate::{
corpus::{Corpus, CorpusId}, corpus::{Corpus, CorpusId},
events::{EventFirer, ProgressReporter}, events::{EventFirer, ProgressReporter},

View File

@ -17,7 +17,7 @@ use serde::Serialize;
#[cfg(feature = "track_hit_feedbacks")] #[cfg(feature = "track_hit_feedbacks")]
use crate::feedbacks::premature_last_result_err; use crate::feedbacks::premature_last_result_err;
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
use crate::statistics::perf_stats::PerfFeature; use crate::monitors::stats::PerfFeature;
use crate::{ use crate::{
corpus::{Corpus, HasCurrentCorpusId, Testcase}, corpus::{Corpus, HasCurrentCorpusId, Testcase},
events::EventFirer, events::EventFirer,

View File

@ -9,7 +9,7 @@ use core::{fmt::Debug, marker::PhantomData};
use libafl_bolts::Named; use libafl_bolts::Named;
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
use crate::statistics::perf_stats::PerfFeature; use crate::monitors::stats::PerfFeature;
use crate::{ use crate::{
corpus::HasCurrentCorpusId, corpus::HasCurrentCorpusId,
executors::{Executor, HasObservers, ShadowExecutor}, executors::{Executor, HasObservers, ShadowExecutor},

View File

@ -7,7 +7,7 @@ use libafl_bolts::{current_time, impl_serdeany, rands::Rand};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
use crate::statistics::perf_stats::PerfFeature; use crate::monitors::stats::PerfFeature;
use crate::{ use crate::{
mark_feature_time, mark_feature_time,
mutators::{MutationResult, Mutator}, mutators::{MutationResult, Mutator},

View File

@ -27,7 +27,7 @@ mod stack;
pub use stack::StageStack; pub use stack::StageStack;
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
use crate::statistics::perf_stats::ClientPerfStats; use crate::monitors::stats::ClientPerfStats;
use crate::{ use crate::{
corpus::{Corpus, CorpusId, HasCurrentCorpusId, HasTestcase, InMemoryCorpus, Testcase}, corpus::{Corpus, CorpusId, HasCurrentCorpusId, HasTestcase, InMemoryCorpus, Testcase},
events::{Event, EventFirer, LogSeverity}, events::{Event, EventFirer, LogSeverity},

View File

@ -1,173 +0,0 @@
//! Global statistics available for Monitors to use
use alloc::string::{String, ToString};
use core::{cmp, time::Duration};
use libafl_bolts::{current_time, format_duration_hms};
#[cfg(feature = "std")]
use serde_json::Value;
use super::ClientStatsManager;
use crate::statistics::ProcessTiming;
#[cfg(feature = "std")]
use crate::statistics::{
user_stats::{AggregatorOps, UserStats, UserStatsValue},
ItemGeometry,
};
impl ClientStatsManager {
/// Time this fuzzing run stated
#[must_use]
pub fn start_time(&self) -> Duration {
self.start_time
}
/// Time this fuzzing run stated
pub fn set_start_time(&mut self, time: Duration) {
self.start_time = time;
}
/// Get global stats.
///
/// This global stats will be cached until the underlined client stats are modified.
pub fn global_stats(&mut self) -> &GlobalStats {
let global_stats = self.cached_global_stats.get_or_insert_with(|| GlobalStats {
run_time: Duration::ZERO,
run_time_pretty: String::new(),
client_stats_count: self
.client_stats
.iter()
.filter(|client| client.enabled)
.count(),
corpus_size: self
.client_stats
.iter()
.fold(0_u64, |acc, x| acc + x.corpus_size),
objective_size: self
.client_stats
.iter()
.fold(0_u64, |acc, x| acc + x.objective_size),
total_execs: self
.client_stats
.iter()
.fold(0_u64, |acc, x| acc + x.executions),
execs_per_sec: 0.0,
execs_per_sec_pretty: String::new(),
});
// Time-related data are always re-computed, since it is related with current time.
let cur_time = current_time();
global_stats.run_time = cur_time - self.start_time;
global_stats.run_time_pretty = format_duration_hms(&global_stats.run_time);
global_stats.execs_per_sec = self
.client_stats
.iter_mut()
.fold(0.0, |acc, x| acc + x.execs_per_sec(cur_time));
global_stats
.execs_per_sec_pretty
.push_str(&super::super::prettify_float(global_stats.execs_per_sec));
global_stats
}
/// Get process timing. `execs_per_sec_pretty` could be retrieved from `GlobalStats`.
#[must_use]
pub fn process_timing(&self, execs_per_sec_pretty: String) -> ProcessTiming {
let mut total_process_timing = ProcessTiming::new();
total_process_timing.exec_speed = execs_per_sec_pretty;
if self.client_stats().len() > 1 {
let mut new_path_time = Duration::default();
let mut new_objectives_time = Duration::default();
for client in self.client_stats().iter().filter(|client| client.enabled()) {
new_path_time = client.last_corpus_time().max(new_path_time);
new_objectives_time = client.last_objective_time().max(new_objectives_time);
}
if new_path_time > self.start_time() {
total_process_timing.last_new_entry = new_path_time - self.start_time();
}
if new_objectives_time > self.start_time() {
total_process_timing.last_saved_solution = new_objectives_time - self.start_time();
}
}
total_process_timing
}
/// Get map density
#[must_use]
pub fn map_density(&self) -> String {
self.client_stats()
.iter()
.filter(|client| client.enabled())
.filter_map(|client| client.get_user_stats("edges"))
.map(ToString::to_string)
.fold("0%".to_string(), cmp::max)
}
/// Get item geometry
#[cfg(feature = "std")]
#[must_use]
pub fn item_geometry(&self) -> ItemGeometry {
let mut total_item_geometry = ItemGeometry::new();
if self.client_stats().len() < 2 {
return total_item_geometry;
}
let mut ratio_a: u64 = 0;
let mut ratio_b: u64 = 0;
for client in self.client_stats().iter().filter(|client| client.enabled()) {
let afl_stats = client
.get_user_stats("AflStats")
.map_or("None".to_string(), ToString::to_string);
let stability = client.get_user_stats("stability").map_or(
UserStats::new(UserStatsValue::Ratio(0, 100), AggregatorOps::Avg),
Clone::clone,
);
if afl_stats != "None" {
let default_json = serde_json::json!({
"pending": 0,
"pend_fav": 0,
"imported": 0,
"own_finds": 0,
});
let afl_stats_json: Value =
serde_json::from_str(afl_stats.as_str()).unwrap_or(default_json);
total_item_geometry.pending +=
afl_stats_json["pending"].as_u64().unwrap_or_default();
total_item_geometry.pend_fav +=
afl_stats_json["pend_fav"].as_u64().unwrap_or_default();
total_item_geometry.own_finds +=
afl_stats_json["own_finds"].as_u64().unwrap_or_default();
total_item_geometry.imported +=
afl_stats_json["imported"].as_u64().unwrap_or_default();
}
if let UserStatsValue::Ratio(a, b) = stability.value() {
ratio_a += a;
ratio_b += b;
}
}
total_item_geometry.stability = format!("{}%", ratio_a * 100 / ratio_b);
total_item_geometry
}
}
/// Global statistics which aggregates client stats.
#[derive(Debug)]
pub struct GlobalStats {
/// Run time since started
pub run_time: Duration,
/// Run time since started
pub run_time_pretty: String,
/// Count the number of enabled client stats
pub client_stats_count: usize,
/// Amount of elements in the corpus (combined for all children)
pub corpus_size: u64,
/// Amount of elements in the objectives (combined for all children)
pub objective_size: u64,
/// Total executions
pub total_execs: u64,
/// Executions per second
pub execs_per_sec: f64,
/// Executions per second
pub execs_per_sec_pretty: String,
}