This commit is contained in:
Andrew Phillips
2026-02-19 13:57:39 -04:00
parent a72395fe83
commit fdeb5f7951
82 changed files with 2756 additions and 2018 deletions

View File

@@ -1,44 +1,47 @@
use log::debug;
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Mutex;
use once_cell::sync::Lazy;
pub mod cwd;
pub mod digest;
pub mod env;
pub mod exec;
pub mod hostname;
pub mod keep_pid;
#[cfg(feature = "magic")]
pub mod magic_file;
pub mod exec;
pub mod digest;
pub mod read_time;
pub mod read_rate;
pub mod hostname;
pub mod cwd;
pub mod user;
pub mod read_time;
pub mod shell;
pub mod shell_pid;
pub mod keep_pid;
pub mod env;
pub mod text;
pub mod user;
// pub mod text; // Removed duplicate
pub use digest::DigestMetaPlugin;
pub use exec::MetaPluginExec;
#[cfg(feature = "magic")]
pub use magic_file::MagicFileMetaPlugin;
pub use exec::MetaPluginExec;
pub use digest::DigestMetaPlugin;
// pub use text::TextMetaPlugin; // Removed duplicate
pub use read_time::ReadTimeMetaPlugin;
pub use read_rate::ReadRateMetaPlugin;
pub use hostname::HostnameMetaPlugin;
pub use cwd::CwdMetaPlugin;
pub use user::UserMetaPlugin;
pub use env::EnvMetaPlugin;
pub use hostname::HostnameMetaPlugin;
pub use keep_pid::KeepPidMetaPlugin;
pub use read_rate::ReadRateMetaPlugin;
pub use read_time::ReadTimeMetaPlugin;
pub use shell::ShellMetaPlugin;
pub use shell_pid::ShellPidMetaPlugin;
pub use keep_pid::KeepPidMetaPlugin;
pub use env::EnvMetaPlugin;
pub use user::UserMetaPlugin;
#[cfg(not(feature = "magic"))]
pub use magic_file::FallbackMagicFileMetaPlugin as MagicFileMetaPlugin;
type PluginConstructor = fn(Option<HashMap<String, serde_yaml::Value>>, Option<HashMap<String, serde_yaml::Value>>) -> Box<dyn MetaPlugin>;
type PluginConstructor = fn(
Option<HashMap<String, serde_yaml::Value>>,
Option<HashMap<String, serde_yaml::Value>>,
) -> Box<dyn MetaPlugin>;
/// Represents metadata to be stored.
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -78,7 +81,7 @@ impl BaseMetaPlugin {
pub fn new() -> Self {
Self::default()
}
/// Returns a reference to the outputs mapping.
///
/// # Returns
@@ -87,7 +90,7 @@ impl BaseMetaPlugin {
pub fn outputs(&self) -> &std::collections::HashMap<String, serde_yaml::Value> {
&self.outputs
}
/// Returns a mutable reference to the outputs mapping.
///
/// # Returns
@@ -96,7 +99,7 @@ impl BaseMetaPlugin {
pub fn outputs_mut(&mut self) -> &mut std::collections::HashMap<String, serde_yaml::Value> {
&mut self.outputs
}
/// Returns a reference to the options mapping.
///
/// # Returns
@@ -105,7 +108,7 @@ impl BaseMetaPlugin {
pub fn options(&self) -> &std::collections::HashMap<String, serde_yaml::Value> {
&self.options
}
/// Returns a mutable reference to the options mapping.
///
/// # Returns
@@ -114,7 +117,7 @@ impl BaseMetaPlugin {
pub fn options_mut(&mut self) -> &mut std::collections::HashMap<String, serde_yaml::Value> {
&mut self.options
}
/// Helper function to initialize plugin options and outputs.
///
/// # Arguments
@@ -130,9 +133,12 @@ impl BaseMetaPlugin {
) {
// Set default outputs
for output_name in default_outputs {
self.outputs.insert(output_name.to_string(), serde_yaml::Value::String(output_name.to_string()));
self.outputs.insert(
output_name.to_string(),
serde_yaml::Value::String(output_name.to_string()),
);
}
// Apply provided options and outputs
if let Some(opts) = options {
for (key, value) in opts {
@@ -158,7 +164,7 @@ impl MetaPlugin for BaseMetaPlugin {
// This might not be used, but we need to satisfy the trait
MetaPluginType::Text
}
/// Returns a reference to the outputs mapping.
///
/// # Returns
@@ -167,7 +173,7 @@ impl MetaPlugin for BaseMetaPlugin {
fn outputs(&self) -> &std::collections::HashMap<String, serde_yaml::Value> {
&self.outputs
}
/// Returns a mutable reference to the outputs mapping.
///
/// # Returns
@@ -176,7 +182,7 @@ impl MetaPlugin for BaseMetaPlugin {
fn outputs_mut(&mut self) -> &mut std::collections::HashMap<String, serde_yaml::Value> {
&mut self.outputs
}
/// Returns a reference to the options mapping.
///
/// # Returns
@@ -185,7 +191,7 @@ impl MetaPlugin for BaseMetaPlugin {
fn options(&self) -> &std::collections::HashMap<String, serde_yaml::Value> {
&self.options
}
/// Returns a mutable reference to the options mapping.
///
/// # Returns
@@ -196,7 +202,18 @@ impl MetaPlugin for BaseMetaPlugin {
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash, strum::EnumIter, strum::Display, strum::EnumString, Serialize, Deserialize)]
#[derive(
Debug,
Eq,
PartialEq,
Clone,
Hash,
strum::EnumIter,
strum::Display,
strum::EnumString,
Serialize,
Deserialize,
)]
#[strum(serialize_all = "snake_case", ascii_case_insensitive)]
pub enum MetaPluginType {
MagicFile,
@@ -225,7 +242,11 @@ pub enum MetaPluginType {
/// # Returns
///
/// An optional `MetaData` if the output is enabled, `None` if disabled.
pub fn process_metadata_outputs(internal_name: &str, value: serde_yaml::Value, outputs: &std::collections::HashMap<String, serde_yaml::Value>) -> Option<MetaData> {
pub fn process_metadata_outputs(
internal_name: &str,
value: serde_yaml::Value,
outputs: &std::collections::HashMap<String, serde_yaml::Value>,
) -> Option<MetaData> {
// Check if this output is disabled
if let Some(mapping) = outputs.get(internal_name) {
// Check for null to disable the output
@@ -235,7 +256,8 @@ pub fn process_metadata_outputs(internal_name: &str, value: serde_yaml::Value, o
}
// Check for boolean false to disable the output
if let Some(false_val) = mapping.as_bool()
&& !false_val {
&& !false_val
{
debug!("META: Skipping disabled output: {}", internal_name);
return None;
}
@@ -246,45 +268,66 @@ pub fn process_metadata_outputs(internal_name: &str, value: serde_yaml::Value, o
serde_yaml::Value::Bool(b) => b.to_string(),
serde_yaml::Value::Number(n) => n.to_string(),
serde_yaml::Value::String(s) => s.clone(),
serde_yaml::Value::Sequence(_) => serde_yaml::to_string(&value).unwrap_or_else(|_| "".to_string()),
serde_yaml::Value::Mapping(_) => serde_yaml::to_string(&value).unwrap_or_else(|_| "".to_string()),
serde_yaml::Value::Tagged(_) => serde_yaml::to_string(&value).unwrap_or_else(|_| "".to_string()),
serde_yaml::Value::Sequence(_) => {
serde_yaml::to_string(&value).unwrap_or_else(|_| "".to_string())
}
serde_yaml::Value::Mapping(_) => {
serde_yaml::to_string(&value).unwrap_or_else(|_| "".to_string())
}
serde_yaml::Value::Tagged(_) => {
serde_yaml::to_string(&value).unwrap_or_else(|_| "".to_string())
}
};
debug!("META: Processing metadata: internal_name={}, custom_name={}, value={}", internal_name, custom_name, value_str);
debug!(
"META: Processing metadata: internal_name={}, custom_name={}, value={}",
internal_name, custom_name, value_str
);
return Some(MetaData {
name: custom_name.to_string(),
value: value_str,
});
}
}
// Convert the value to a string representation
let value_str = match &value {
serde_yaml::Value::Null => "null".to_string(),
serde_yaml::Value::Bool(b) => b.to_string(),
serde_yaml::Value::Number(n) => n.to_string(),
serde_yaml::Value::String(s) => s.clone(),
serde_yaml::Value::Sequence(_) => serde_yaml::to_string(&value).unwrap_or_else(|_| "".to_string()),
serde_yaml::Value::Mapping(_) => serde_yaml::to_string(&value).unwrap_or_else(|_| "".to_string()),
serde_yaml::Value::Tagged(_) => serde_yaml::to_string(&value).unwrap_or_else(|_| "".to_string()),
serde_yaml::Value::Sequence(_) => {
serde_yaml::to_string(&value).unwrap_or_else(|_| "".to_string())
}
serde_yaml::Value::Mapping(_) => {
serde_yaml::to_string(&value).unwrap_or_else(|_| "".to_string())
}
serde_yaml::Value::Tagged(_) => {
serde_yaml::to_string(&value).unwrap_or_else(|_| "".to_string())
}
};
// Default: use internal name as output name
debug!("META: Processing metadata: name={}, value={}", internal_name, value_str);
debug!(
"META: Processing metadata: name={}, value={}",
internal_name, value_str
);
Some(MetaData {
name: internal_name.to_string(),
value: value_str,
})
}
pub trait MetaPlugin where Self: 'static {
pub trait MetaPlugin
where
Self: 'static,
{
/// Returns the type of this meta plugin.
///
/// # Returns
///
/// The `MetaPluginType` enum variant for this plugin.
fn meta_type(&self) -> MetaPluginType;
/// Checks if the plugin is supported on the current system.
///
/// # Returns
@@ -293,7 +336,7 @@ pub trait MetaPlugin where Self: 'static {
fn is_supported(&self) -> bool {
true
}
/// Checks if the plugin is internal (built-in).
///
/// # Returns
@@ -302,7 +345,7 @@ pub trait MetaPlugin where Self: 'static {
fn is_internal(&self) -> bool {
true
}
/// Checks if the plugin is already finalized.
///
/// # Returns
@@ -311,14 +354,14 @@ pub trait MetaPlugin where Self: 'static {
fn is_finalized(&self) -> bool {
false
}
/// Sets the finalized state (only for plugins that can track this).
///
/// # Arguments
///
/// * `_finalized` - The new finalized state (unused in default).
fn set_finalized(&mut self, _finalized: bool) {}
/// Updates the meta plugin with new data.
///
/// # Arguments
@@ -348,7 +391,7 @@ pub trait MetaPlugin where Self: 'static {
is_finalized: true,
}
}
/// Gets program information for display in status.
///
/// # Returns
@@ -357,8 +400,7 @@ pub trait MetaPlugin where Self: 'static {
fn program_info(&self) -> Option<(&str, Vec<&str>)> {
None
}
/// Initializes the plugin.
///
/// # Returns
@@ -371,7 +413,7 @@ pub trait MetaPlugin where Self: 'static {
is_finalized: false,
}
}
/// Returns a reference to the outputs mapping.
///
/// # Returns
@@ -379,11 +421,11 @@ pub trait MetaPlugin where Self: 'static {
/// An empty `HashMap` (default implementation).
fn outputs(&self) -> &std::collections::HashMap<String, serde_yaml::Value> {
use once_cell::sync::Lazy;
static EMPTY: Lazy<std::collections::HashMap<String, serde_yaml::Value>> =
Lazy::new(|| std::collections::HashMap::new());
static EMPTY: Lazy<std::collections::HashMap<String, serde_yaml::Value>> =
Lazy::new(std::collections::HashMap::new);
&EMPTY
}
/// Returns a mutable reference to the outputs mapping.
///
/// # Panics
@@ -392,7 +434,7 @@ pub trait MetaPlugin where Self: 'static {
fn outputs_mut(&mut self) -> &mut std::collections::HashMap<String, serde_yaml::Value> {
panic!("outputs_mut() not implemented for this plugin")
}
/// Returns a reference to the options mapping.
///
/// # Returns
@@ -400,11 +442,11 @@ pub trait MetaPlugin where Self: 'static {
/// An empty `HashMap` (default implementation).
fn options(&self) -> &std::collections::HashMap<String, serde_yaml::Value> {
use once_cell::sync::Lazy;
static EMPTY: Lazy<std::collections::HashMap<String, serde_yaml::Value>> =
Lazy::new(|| std::collections::HashMap::new());
static EMPTY: Lazy<std::collections::HashMap<String, serde_yaml::Value>> =
Lazy::new(std::collections::HashMap::new);
&EMPTY
}
/// Returns a mutable reference to the options mapping.
///
/// # Panics
@@ -413,7 +455,7 @@ pub trait MetaPlugin where Self: 'static {
fn options_mut(&mut self) -> &mut std::collections::HashMap<String, serde_yaml::Value> {
panic!("options_mut() not implemented for this plugin")
}
/// Gets the default output names this plugin can produce.
///
/// # Returns
@@ -423,20 +465,22 @@ pub trait MetaPlugin where Self: 'static {
// Default implementation returns the meta type as a string
vec![self.meta_type().to_string()]
}
/// Method to downcast to concrete type (for checking finalization state).
///
/// # Returns
///
/// A mutable reference to `self` as `dyn Any`.
fn as_any_mut(&mut self) -> &mut dyn std::any::Any where Self: Sized {
fn as_any_mut(&mut self) -> &mut dyn std::any::Any
where
Self: Sized,
{
self
}
}
/// Global registry for meta plugins.
static META_PLUGIN_REGISTRY: Lazy<Mutex<HashMap<MetaPluginType, PluginConstructor>>> =
static META_PLUGIN_REGISTRY: Lazy<Mutex<HashMap<MetaPluginType, PluginConstructor>>> =
Lazy::new(|| Mutex::new(HashMap::new()));
/// Register a meta plugin with the global registry.
@@ -445,11 +489,11 @@ static META_PLUGIN_REGISTRY: Lazy<Mutex<HashMap<MetaPluginType, PluginConstructo
///
/// * `meta_plugin_type` - The type of the meta plugin to register.
/// * `constructor` - The constructor function for creating plugin instances.
pub fn register_meta_plugin(
meta_plugin_type: MetaPluginType,
constructor: PluginConstructor
) {
META_PLUGIN_REGISTRY.lock().unwrap().insert(meta_plugin_type, constructor);
pub fn register_meta_plugin(meta_plugin_type: MetaPluginType, constructor: PluginConstructor) {
META_PLUGIN_REGISTRY
.lock()
.unwrap()
.insert(meta_plugin_type, constructor);
}
pub fn get_meta_plugin(
@@ -461,7 +505,7 @@ pub fn get_meta_plugin(
if let Some(constructor) = registry.get(&meta_plugin_type) {
return constructor(options, outputs);
}
// Fallback for unknown plugins
panic!("Meta plugin {:?} not registered", meta_plugin_type);
}