diff --git a/geyser-plugin-interface/src/geyser_plugin_interface.rs b/geyser-plugin-interface/src/geyser_plugin_interface.rs index 43c31f749b6e8f..037aedf8b87e89 100644 --- a/geyser-plugin-interface/src/geyser_plugin_interface.rs +++ b/geyser-plugin-interface/src/geyser_plugin_interface.rs @@ -321,6 +321,35 @@ pub type Result = std::result::Result; /// Geyser plugins must describe desired behavior for load and unload, /// as well as how they will handle streamed data. pub trait GeyserPlugin: Any + Send + Sync + std::fmt::Debug { + /// The callback to allow the plugin to setup the logging configuration using the logger + /// and log level specified by the validator. Will be called first on load/reload, before any other + /// callback, and only called once. + /// # Examples + /// + /// ``` + /// use solana_geyser_plugin_interface::geyser_plugin_interface::{GeyserPlugin, + /// GeyserPluginError, Result}; + /// + /// #[derive(Debug)] + /// struct SamplePlugin; + /// impl GeyserPlugin for SamplePlugin { + /// fn setup_logger(&self, logger: &'static dyn log::Log, level: log::LevelFilter) -> Result<()> { + /// log::set_max_level(level); + /// if let Err(err) = log::set_logger(logger) { + /// return Err(GeyserPluginError::Custom(Box::new(err))); + /// } + /// Ok(()) + /// } + /// fn name(&self) -> &'static str { + /// &"sample" + /// } + /// } + /// ``` + #[allow(unused_variables)] + fn setup_logger(&self, logger: &'static dyn log::Log, level: log::LevelFilter) -> Result<()> { + Ok(()) + } + fn name(&self) -> &'static str; /// The callback called when a plugin is loaded by the system, diff --git a/geyser-plugin-manager/src/geyser_plugin_manager.rs b/geyser-plugin-manager/src/geyser_plugin_manager.rs index 9e353b0254ffba..72aa331cc61478 100644 --- a/geyser-plugin-manager/src/geyser_plugin_manager.rs +++ b/geyser-plugin-manager/src/geyser_plugin_manager.rs @@ -107,6 +107,8 @@ impl GeyserPluginManager { }); } + setup_logger_for_plugin(&*new_plugin)?; + // Call on_load and push plugin new_plugin .on_load(new_config_file, false) @@ -193,6 +195,8 @@ impl GeyserPluginManager { }); } + setup_logger_for_plugin(&*new_plugin)?; + // Attempt to on_load with new plugin match new_plugin.on_load(new_parsed_config_file, true) { // On success, push plugin and library @@ -227,6 +231,20 @@ impl GeyserPluginManager { } } +// Initialize logging for the plugin +fn setup_logger_for_plugin(new_plugin: &dyn GeyserPlugin) -> Result<(), jsonrpc_core::Error> { + new_plugin + .setup_logger(log::logger(), log::max_level()) + .map_err(|setup_logger_err| jsonrpc_core::Error { + code: ErrorCode::InvalidRequest, + message: format!( + "setup_logger method of plugin {} failed: {setup_logger_err}", + new_plugin.name() + ), + data: None, + }) +} + #[derive(Debug)] pub enum GeyserPluginManagerRequest { ReloadPlugin {