Skip to content

Commit f30b054

Browse files
authored
Add combined monitor (#2900)
* Add combined monitor * Sync start_time when initializing * Use clone_from instead of clone to make clippy happy
1 parent 7c84a79 commit f30b054

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed

libafl/src/monitors/mod.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,3 +1302,79 @@ impl Default for ClientPerfMonitor {
13021302
Self::new()
13031303
}
13041304
}
1305+
1306+
/// A combined monitor consisting of multiple [`Monitor`]s
1307+
#[derive(Debug, Clone)]
1308+
pub struct CombinedMonitor<A, B> {
1309+
first: A,
1310+
second: B,
1311+
start_time: Duration,
1312+
/// Client stats. This will be maintained to be consistent with
1313+
/// client stats of first and second monitor.
1314+
///
1315+
/// Currently, the client stats will be synced to first and second
1316+
/// before each display call.
1317+
client_stats: Vec<ClientStats>,
1318+
}
1319+
1320+
impl<A: Monitor, B: Monitor> CombinedMonitor<A, B> {
1321+
/// Create a new combined monitor
1322+
pub fn new(mut first: A, mut second: B) -> Self {
1323+
let start_time = current_time();
1324+
first.set_start_time(start_time);
1325+
second.set_start_time(start_time);
1326+
Self {
1327+
first,
1328+
second,
1329+
start_time,
1330+
client_stats: vec![],
1331+
}
1332+
}
1333+
}
1334+
1335+
impl<A: Monitor, B: Monitor> Monitor for CombinedMonitor<A, B> {
1336+
fn client_stats_mut(&mut self) -> &mut Vec<ClientStats> {
1337+
&mut self.client_stats
1338+
}
1339+
1340+
fn client_stats(&self) -> &[ClientStats] {
1341+
&self.client_stats
1342+
}
1343+
1344+
fn start_time(&self) -> Duration {
1345+
self.start_time
1346+
}
1347+
1348+
fn set_start_time(&mut self, time: Duration) {
1349+
self.start_time = time;
1350+
self.first.set_start_time(time);
1351+
self.second.set_start_time(time);
1352+
}
1353+
1354+
fn display(&mut self, event_msg: &str, sender_id: ClientId) {
1355+
self.first.client_stats_mut().clone_from(&self.client_stats);
1356+
self.first.display(event_msg, sender_id);
1357+
self.second
1358+
.client_stats_mut()
1359+
.clone_from(&self.client_stats);
1360+
self.second.display(event_msg, sender_id);
1361+
}
1362+
1363+
fn aggregate(&mut self, name: &str) {
1364+
self.first.aggregate(name);
1365+
self.second.aggregate(name);
1366+
}
1367+
}
1368+
1369+
/// Variadic macro to create a chain of [`Monitor`]
1370+
#[macro_export]
1371+
macro_rules! combine_monitor {
1372+
( $last:expr ) => { $last };
1373+
1374+
( $last:expr, ) => { $last };
1375+
1376+
( $head:expr, $($tail:expr),+ $(,)?) => {
1377+
// recursive call
1378+
$crate::monitors::CombinedMonitor::new($head , $crate::combine_monitor!($($tail),+))
1379+
};
1380+
}

0 commit comments

Comments
 (0)