gear_node_wrapper/
log.rs

1//! Log filter for the node
2use anyhow::{Result, anyhow};
3use smallvec::SmallVec;
4use std::{
5    io::{BufRead, BufReader, Read},
6    process::Child,
7    sync::{Arc, RwLock},
8    thread,
9    thread::JoinHandle,
10};
11
12const DEFAULT_LOGS_LIMIT: usize = 256;
13const BLOCK_INITIALIZATION: &str = "Imported #1";
14
15/// Log filter for the node
16#[derive(Default)]
17pub struct Log {
18    /// Join handle of logs
19    handle: Option<JoinHandle<()>>,
20    /// Filtered logs from the node output
21    pub logs: Arc<RwLock<SmallVec<[String; DEFAULT_LOGS_LIMIT]>>>,
22}
23
24impl Log {
25    /// New log with holding limits
26    pub fn new(limit: Option<usize>) -> Self {
27        let mut this = Log::default();
28        if let Some(limit) = limit {
29            this.resize(limit);
30        }
31
32        this
33    }
34
35    /// Resize the limit logs that this instance holds
36    pub fn resize(&mut self, limit: usize) {
37        if let Ok(mut logs) = self.logs.write() {
38            if limit > DEFAULT_LOGS_LIMIT {
39                logs.grow(limit)
40            } else {
41                logs.reserve(limit)
42            }
43        }
44    }
45
46    /// Spawn logs from the child process
47    pub fn spawn(&mut self, ps: &mut Child) -> Result<()> {
48        let Some(stderr) = ps.stderr.take() else {
49            return Err(anyhow!("Not stderr found"));
50        };
51
52        // Blocking after initialization.
53        let mut reader = BufReader::new(stderr);
54        for line in reader.by_ref().lines().map_while(|result| result.ok()) {
55            if line.contains(BLOCK_INITIALIZATION) {
56                break;
57            }
58        }
59
60        // Mapping logs to memory
61        let logs = Arc::clone(&self.logs);
62        let handle = thread::spawn(move || {
63            for line in reader.lines().map_while(|result| result.ok()) {
64                if let Ok(mut logs) = logs.write() {
65                    logs.push(line);
66                }
67            }
68        });
69
70        self.handle = Some(handle);
71        Ok(())
72    }
73}