Skip to content

Commit

Permalink
Merge pull request #29 from Thaumy/available-events
Browse files Browse the repository at this point in the history
Add helper functions for `TracepointEvent`
  • Loading branch information
OptimatistCorp authored Mar 20, 2024
2 parents 1682462 + 65f51de commit 78284a2
Showing 1 changed file with 85 additions and 0 deletions.
85 changes: 85 additions & 0 deletions src/perf_event/event/tracepoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,25 @@
// see <https://www.gnu.org/licenses/>.

use crate::perf_event::event::Event;
use std::num::ParseIntError;
use std::ops::Not;
use std::path::PathBuf;
use std::{fs, io};
use thiserror::Error;

#[derive(Error, Debug)]
pub enum Error {
#[error("Event name is invalid")]
InvalidEventName,
#[error("Event is unsupported")]
UnsupportedEvent,
#[error("Failed to find tracefs")]
FailedToFindTracefs,
#[error("Failed to parse id file: {0}")]
FailedToParseIdFile(ParseIntError),
#[error("I/O error: {0}")]
IoError(io::Error),
}

#[derive(Clone, Debug)]
pub struct TracepointEvent {
Expand All @@ -24,10 +43,76 @@ impl TracepointEvent {
pub const fn new(id: u64) -> Self {
Self { id }
}

/// The format of the event name is `lhs:rhs`, for example: `sched:sched_switch`
///
/// For all available events, see: `/sys/kernel/debug/tracing/available_events`
pub fn from_event_name(event_name: &str) -> Result<Self, Error> {
let mut split = event_name.split(':');
let path = match (split.next(), split.next()) {
(_, None) => return Err(Error::InvalidEventName),
(None, _) => return Err(Error::InvalidEventName),
(Some(lhs), Some(rhs)) => {
let mut path = tracefs_path()?;
path.push("events");
path.push(lhs);
path.push(rhs);
path.push("id");
path
}
};

if path.exists().not() {
return Err(Error::UnsupportedEvent);
}

let contents = fs::read_to_string(path).map_err(Error::IoError)?;
let id =
str::parse::<u64>(&contents.replace('\n', "")).map_err(Error::FailedToParseIdFile)?;

Ok(Self { id })
}

/// Get all available event names from `/sys/kernel/debug/tracing/available_events`
pub fn available_event_names() -> Result<Vec<String>, Error> {
let mut path = tracefs_path()?;
path.push("available_events");

let contents = fs::read_to_string(path).map_err(Error::IoError)?;
let lines: Vec<String> = contents.lines().map(|it| it.to_string()).collect();

Ok(lines)
}
}

fn tracefs_path() -> Result<PathBuf, Error> {
let contents = fs::read_to_string("/proc/mounts").map_err(Error::IoError)?;

contents
.lines()
.find(|line| line.starts_with("tracefs"))
.and_then(|line| line.split(' ').nth(1))
.ok_or_else(|| Error::FailedToFindTracefs)
.map(PathBuf::from)
}

impl From<TracepointEvent> for Event {
fn from(value: TracepointEvent) -> Self {
Self::Tracepoint(value)
}
}

#[test]
fn test_from_event_name() {
let ev_name = "kmem:kfree";
let ev = TracepointEvent::from_event_name(ev_name);
dbg!(ev.unwrap());
}

#[test]
fn test_available_event_names() {
let ev_names = TracepointEvent::available_event_names();
dbg!(&ev_names);
let ev_names = ev_names.unwrap();
assert!(ev_names.len() > 0);
}

0 comments on commit 78284a2

Please sign in to comment.