Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Source Implementation

Implementing a new metric source in Joule Profiler is straightforward. By implementing the MetricReader trait, you only need to define the core measurement logic (measure, retrieve, get_sensors, to_metrics, get_name) and optionally override init or join if your source requires setup or polling logic. This design makes it easy to add new sources without boilerplate.

use joule_profiler_core::{
    sensor::{Sensor, Sensors},
    source::{MetricReader, MetricSourceError},
    types::{Metric, Metrics},
    unit::{MetricUnit, Unit, UnitPrefix},
};

const MY_SOURCE_UNIT: MetricUnit = MetricUnit {
    prefix: UnitPrefix::None,
    unit: Unit::Count,
};

#[derive(Default)]
struct MySource {
    count: u64,
}

impl MySource {
    pub fn new() -> Self {
        Self::default()
    }
}

impl MetricReader for MySource {
    type Type = u64;

    type Error = MetricSourceError;

    async fn measure(&mut self) -> Result<(), Self::Error> {
        self.count += 1;
        Ok(())
    }

    async fn retrieve(&mut self) -> Result<Self::Type, Self::Error> {
        let count = self.count;
        self.count = 0;
        Ok(count)
    }

    fn get_sensors(&self) -> Result<Sensors, Self::Error> {
        let sensor = Sensor::new("value", MY_SOURCE_UNIT, "my_source")
        Ok(vec![sensor])
    }

    fn to_metrics(&self, count: u64) -> Result<Metrics, Self::Error> {
        let metric = Metric::new("value", count, MY_SOURCE_UNIT, "my_source");
        Ok(vec![metric])
    }

    fn get_name() -> &'static str {
        "my_source"
    }
}