Basic setup
Prerequisites
Before attempting anything, please check that you have a recent version of the Rust toolchain (at least 1.76 for now). You can run rustc --version
to check your version. The easiest way to install a recent version of Rust is to use rustup.
Creating the plugin crate
The first thing to do is to initialize a new crate for the plugin. Alumet plugins are not executables by themselves, they are library crates.
You have two options:
- fork the official Alumet repository and develop there (best if you want to contribute to Alumet)
- work in your own repository (best if you want to be independent)
Creating the plugin in a fork of the official repository
Fork the Alumet repository on GitHub.
Clone your fork with git clone
and open the root directory of Alumet.
You should see several files and folders:
.
├── Cargo.lock
├── Cargo.toml
├── LICENSE
├── LICENSE.fr.txt
├── README.md
├── alumet/
├── app-agent/
├── plugin-csv/
├── plugin-nvidia/
├── plugin-rapl/
├── plugin-relay/
├── target/
├── ...
Let's make a crate for your plugin! By convention, plugins contained in the main repository should be prefixed with plugin-
:
cargo init --lib plugin-example
This will create a new directory named plugin-example
, with some files in it.
Cargo should also modify the root Cargo.toml
to add your plugin to the list of members
, like this:
members = [
"alumet",
# ... other crates here
# the line below has been added automatically
"plugin-example",
]
Finally, use cargo add
to declare some dependencies. Every plugin needs to depend on at least alumet
and anyhow
. We also add log
to display nice log messages (avoid println!
in Alumet!).
cargo add alumet anyhow log
Make sure that the alumet
dependency is local and does not include a version number:
[package]
name = "plugin-example"
version = "0.1.0"
edition = "2021"
[dependencies]
alumet = { path = "../alumet" } # LOCAL + NO VERSION
anyhow = "1.0"
log = "0.4"
Creating the plugin in a separate repository
Initialize a crate with cargo:
cargo init --lib plugin-example
Finally, use cargo add
to declare some dependencies. Every plugin needs to depend on at least alumet
and anyhow
. We'll also add log
to display nice log messages (avoid println!
in Alumet!).
cargo add alumet anyhow log
Since your plugin is not in the main repository of Alumet, the dependency on alumet
will not be local, but rather downloaded from crates.io
.
Coding - v0.1
Now, the fun part: let's code your plugin!
Plugin Structure
Open the lib.rs
file in your plugin source directory. For now, it contains a minimal library generated by cargo init
. You will replace it with a minimal Alumet plugin.
To define a (static) Alumet plugin, you just need two things:
- a structure
- an implementation of the
AlumetPlugin
trait for this structure
Here is what it looks like:
use alumet::plugin::{rust::AlumetPlugin, AlumetPluginStart, ConfigTable};
pub struct ExamplePlugin;
impl AlumetPlugin for ExamplePlugin {
fn name() -> &'static str {
"example" // the name of your plugin, in lowercase, without the "plugin-" prefix
}
fn version() -> &'static str {
env!("CARGO_PKG_VERSION") // gets the version from the Cargo.toml of the plugin crate
}
fn default_config() -> anyhow::Result<Option<ConfigTable>> {
Ok(None) // no config for the moment
}
fn init(config: ConfigTable) -> anyhow::Result<Box<Self>> {
Ok(Box::new(ExamplePlugin))
}
fn start(&mut self, alumet: &mut AlumetPluginStart) -> anyhow::Result<()> {
log::info!("Hello!");
Ok(())
}
fn stop(&mut self) -> anyhow::Result<()> {
log::info!("Bye!");
Ok(())
}
}
Note that the plugin structure is public. It needs to be, otherwise agents (executable applications that perform the measurements with Alumet) won't be able to use the plugin. For now, the structure is empty. It can contain anything you want, in particular configuration options. We will show an example later.
Running your plugin
To try your plugin, you need to modify an Alumet agent so that it loads the plugin on startup.
If you develop your plugin outside of the main Alumet repository, you probably have your own agent, maybe based on a local copy of official Alumet agents. If you develop your plugin in the main Alumet repository, here is what you need to do:
- Choose an agent to modify.
- Add your plugin as a dependency of the agent.
- Edit one or two lines or code to make the agent load your plugin.
For this tutorial, we will modify the "local" agent, which works on its own (unlike the relay mode for instance). In the Alumet repository, open a Terminal in the app-agent
folder.
Add your plugin to dependencies of the agent:
cargo add plugin-example
Open app-agent/src/bin/local.rs
and add your plugin to the list of plugins. For a first test, you can remove other plugins in order to see the messages of your plugin more easily. Let's keep the CSV plugin, though. It will be useful to see what the measurements produced by your plugin (in the next steps of the tutorial).
let plugins = static_plugins![
- plugin_rapl::RaplPlugin,
- // ... (other plugins)
+ plugin_example::ExamplePlugin,
plugin_csv::CsvPlugin,
];
Note: with cargo, we use the name that we declared for the crate, plugin-example
(look at plugin-example/Cargo.toml
), but in code we use plugin_example
. This is because hyphens are not valid characters in Rust identifiers, hence they are converted to underscores.
Finally, you can test your plugin! Run the local agent:
cargo run --bin alumet-local-agent --features local_x86
You should see your plugin in the list of enabled plugins, and it should print the message Hello!
(from its start
method).
Stop the agent with Ctrl+C. Your plugin should print the message Bye!
(from its stop
method).