Skip to content

geobeau/ebpf-histogram

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ebpf-histogram

Provides a library to create Prometheus histogram directly from ebpf data structures. It depends on aya-rs and Prometheus, and requires familiarity with both APIs.

Usage

Usage in ebpf: ebpf-histogram-ebpf

Crates.io License

In cargo.toml

ebpf-histogram-ebpf = "0.1.0"
use ebpf_histogram_ebpf::BpfHistogram;

#[derive(Copy, Clone)]
#[repr(C)] // You need to make sure the format will be similar betweem user space and ebpf code
pub struct DiskLatencyHistogramKey {
    pub major: i32,
    pub minor: i32
}

#[map]
static BLOCK_HISTOGRAM: BpfHistogram<DiskLatencyHistogramKey> = BpfHistogram::with_max_entries(1000, 0);


#[btf_tracepoint(function="block_rq_complete")]
pub fn block_rq_complete(ctx: BtfTracePointContext) -> u32 {
    let req: *const vmlinux::request = unsafe { ctx.arg(0) };

    unsafe {
        let timestamp = bpf_ktime_get_ns();
        let disk: vmlinux::gendisk = *((*(*req).q).disk);
        let latency = timestamp - (*req).io_start_time_ns;
        let flags = (*req).cmd_flags & REQ_OP_MASK;
        // This is the only code that matters. It tries to copy the API of Prometheus histogram
        BLOCK_HISTOGRAM.observe(DiskLatencyHistogramKey{ major: disk.major, minor: disk.minors }, latency);
        info!(&ctx, "complete disk {}.{} -> Latency: {}us, (flags: {})", disk.major,disk.minors, latency / 1000, flags);
    }
    return 0
}

Usage in userspace: ebpf-histogram

Crates.io License

In cargo.toml

ebpf-histogram = "0.1.0"
use prometheus::{Opts, Registry, TextEncoder};
use ebpf_histogram::{Histogram, Key, KeyWrapper};


#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
// #[derive(Key)]
#[repr(C)]
pub struct DiskLatencyHistogramKey {
    pub major: i32,
    pub minor: i32
}

unsafe impl Send for DiskLatencyHistogramKey {}
unsafe impl Sync for DiskLatencyHistogramKey {}
unsafe impl Pod for DiskLatencyHistogramKey {}
impl Key for DiskLatencyHistogramKey {
    // Inform which labels pairs will be exposed by Prometheus
    fn get_label_keys() -> Vec<String> {
        return vec!["major".to_string(), "minor".to_string()]
    }

    // Transform the key into labels values every time the collection of metrics is done
    fn get_label_values(&self) -> Vec<String> {
        return vec![self.major.to_string(), self.minor.to_string()]
    }
}


#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
    /*
    Main code
    */

    // Get the map in common with ebpf code
    let map: PerCpuHashMap<_, KeyWrapper<DiskLatencyHistogramKey>, u64> = PerCpuHashMap::try_from(
        bpf.take_map("BLOCK_HISTOGRAM").expect("failed to map BLOCK_HISTOGRAM"),
    )?;

    // Define Prometheus configuration for the metric
    let bucket_opts = Opts::new("test_latency", "test counter help");
    let histogram: Histogram<DiskLatencyHistogramKey> = Histogram::new_from_map(map, bucket_opts);

    // The histogran implement Collect so it can be used like a regular Prometheus metric
    let r = Registry::new();
    r.register(Box::new(histogram)).unwrap();

    // See the documentation of Rust Prometheus to see how to use the metric then
    let mut buffer = String::new();
    let encoder = TextEncoder::new();
    let metric_families = r.gather();
    encoder.encode_utf8(&metric_families, &mut buffer).unwrap();
    println!("{}", buffer);

}

About

Provides helpers to use histogram on aya-rs

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages