diff --git a/index-scheduler/src/features.rs b/index-scheduler/src/features.rs index c18ab98db..744b47f11 100644 --- a/index-scheduler/src/features.rs +++ b/index-scheduler/src/features.rs @@ -43,6 +43,20 @@ impl RoFeatures { } } + pub fn check_logs_route(&self) -> Result<()> { + if self.runtime.logs_route { + Ok(()) + } else { + Err(FeatureNotEnabledError { + disabled_action: "Getting logs", + feature: "logsRoute", + /// Update the discussion link + issue_link: "https://github.com/meilisearch/product/discussions/625", + } + .into()) + } + } + pub fn check_vector(&self, disabled_action: &'static str) -> Result<()> { if self.runtime.vector_store { Ok(()) diff --git a/meilisearch-types/src/features.rs b/meilisearch-types/src/features.rs index d737c618e..f7e09317b 100644 --- a/meilisearch-types/src/features.rs +++ b/meilisearch-types/src/features.rs @@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize}; pub struct RuntimeTogglableFeatures { pub vector_store: bool, pub metrics: bool, + pub logs_route: bool, pub export_puffin_reports: bool, } diff --git a/meilisearch/src/analytics/segment_analytics.rs b/meilisearch/src/analytics/segment_analytics.rs index 6969c9b3d..a38ddaab2 100644 --- a/meilisearch/src/analytics/segment_analytics.rs +++ b/meilisearch/src/analytics/segment_analytics.rs @@ -250,6 +250,7 @@ impl super::Analytics for SegmentAnalytics { struct Infos { env: String, experimental_enable_metrics: bool, + experimental_enable_logs_route: bool, experimental_reduce_indexing_memory_usage: bool, experimental_max_number_of_batched_tasks: usize, db_path: bool, @@ -287,6 +288,7 @@ impl From for Infos { let Opt { db_path, experimental_enable_metrics, + experimental_enable_logs_route, experimental_reduce_indexing_memory_usage, experimental_max_number_of_batched_tasks, http_addr, @@ -333,6 +335,7 @@ impl From for Infos { Self { env, experimental_enable_metrics, + experimental_enable_logs_route, experimental_reduce_indexing_memory_usage, db_path: db_path != PathBuf::from("./data.ms"), import_dump: import_dump.is_some(), diff --git a/meilisearch/src/option.rs b/meilisearch/src/option.rs index 3cff14aa0..d612210c8 100644 --- a/meilisearch/src/option.rs +++ b/meilisearch/src/option.rs @@ -51,6 +51,7 @@ const MEILI_IGNORE_MISSING_DUMP: &str = "MEILI_IGNORE_MISSING_DUMP"; const MEILI_IGNORE_DUMP_IF_DB_EXISTS: &str = "MEILI_IGNORE_DUMP_IF_DB_EXISTS"; const MEILI_DUMP_DIR: &str = "MEILI_DUMP_DIR"; const MEILI_LOG_LEVEL: &str = "MEILI_LOG_LEVEL"; +const MEILI_EXPERIMENTAL_ENABLE_LOGS_ROUTE: &str = "MEILI_EXPERIMENTAL_ENABLE_LOGS_ROUTE"; const MEILI_EXPERIMENTAL_ENABLE_METRICS: &str = "MEILI_EXPERIMENTAL_ENABLE_METRICS"; const MEILI_EXPERIMENTAL_REDUCE_INDEXING_MEMORY_USAGE: &str = "MEILI_EXPERIMENTAL_REDUCE_INDEXING_MEMORY_USAGE"; @@ -309,6 +310,14 @@ pub struct Opt { #[serde(default)] pub experimental_enable_metrics: bool, + // TODO: update the link + /// Experimental logs route feature. For more information, see: + /// + /// Enables the log route on the `POST /logs` endpoint and the `DELETE /logs` to stop receiving logs. + #[clap(long, env = MEILI_EXPERIMENTAL_ENABLE_LOGS_ROUTE)] + #[serde(default)] + pub experimental_enable_logs_route: bool, + /// Experimental RAM reduction during indexing, do not use in production, see: #[clap(long, env = MEILI_EXPERIMENTAL_REDUCE_INDEXING_MEMORY_USAGE)] #[serde(default)] @@ -414,6 +423,7 @@ impl Opt { #[cfg(feature = "analytics")] no_analytics, experimental_enable_metrics, + experimental_enable_logs_route, experimental_reduce_indexing_memory_usage, } = self; export_to_env_if_not_present(MEILI_DB_PATH, db_path); @@ -470,6 +480,10 @@ impl Opt { MEILI_EXPERIMENTAL_ENABLE_METRICS, experimental_enable_metrics.to_string(), ); + export_to_env_if_not_present( + MEILI_EXPERIMENTAL_ENABLE_LOGS_ROUTE, + experimental_enable_logs_route.to_string(), + ); export_to_env_if_not_present( MEILI_EXPERIMENTAL_REDUCE_INDEXING_MEMORY_USAGE, experimental_reduce_indexing_memory_usage.to_string(), diff --git a/meilisearch/src/routes/features.rs b/meilisearch/src/routes/features.rs index 0a7e73ac6..375201a97 100644 --- a/meilisearch/src/routes/features.rs +++ b/meilisearch/src/routes/features.rs @@ -45,6 +45,8 @@ pub struct RuntimeTogglableFeatures { #[deserr(default)] pub metrics: Option, #[deserr(default)] + pub logs_route: Option, + #[deserr(default)] pub export_puffin_reports: Option, } @@ -63,6 +65,7 @@ async fn patch_features( let new_features = meilisearch_types::features::RuntimeTogglableFeatures { vector_store: new_features.0.vector_store.unwrap_or(old_features.vector_store), metrics: new_features.0.metrics.unwrap_or(old_features.metrics), + logs_route: new_features.0.logs_route.unwrap_or(old_features.logs_route), export_puffin_reports: new_features .0 .export_puffin_reports @@ -75,6 +78,7 @@ async fn patch_features( let meilisearch_types::features::RuntimeTogglableFeatures { vector_store, metrics, + logs_route, export_puffin_reports, } = new_features; @@ -83,6 +87,7 @@ async fn patch_features( json!({ "vector_store": vector_store, "metrics": metrics, + "logs_route": logs_route, "export_puffin_reports": export_puffin_reports, }), Some(&req), diff --git a/meilisearch/src/routes/logs.rs b/meilisearch/src/routes/logs.rs index 96228f9aa..bca944d76 100644 --- a/meilisearch/src/routes/logs.rs +++ b/meilisearch/src/routes/logs.rs @@ -10,7 +10,7 @@ use actix_web::{web, HttpResponse}; use deserr::actix_web::AwebJson; use deserr::{DeserializeError, Deserr, ErrorKind, MergeWithError, ValuePointerRef}; use futures_util::Stream; -use meilisearch_auth::AuthController; +use index_scheduler::IndexScheduler; use meilisearch_types::deserr::DeserrJsonError; use meilisearch_types::error::deserr_codes::*; use meilisearch_types::error::{Code, ResponseError}; @@ -213,12 +213,13 @@ fn entry_stream( } pub async fn get_logs( - _auth_controller: GuardedData, Data>, + index_scheduler: GuardedData, Data>, logs: Data, body: AwebJson, ) -> Result { - let opt = body.into_inner(); + index_scheduler.features().check_logs_route()?; + let opt = body.into_inner(); let mut stream = None; logs.modify(|layer| match layer.inner_mut() { @@ -244,9 +245,11 @@ pub async fn get_logs( } pub async fn cancel_logs( - _auth_controller: GuardedData, Data>, + index_scheduler: GuardedData, Data>, logs: Data, ) -> Result { + index_scheduler.features().check_logs_route()?; + if let Err(e) = logs.modify(|layer| *layer.inner_mut() = None) { tracing::error!("Could not free the logs route: {e}"); }