From 07bfed99e65360d62d17c051f6050c7d422ae455 Mon Sep 17 00:00:00 2001 From: Kerollmops Date: Fri, 4 Jul 2025 11:03:14 +0200 Subject: [PATCH 1/2] Expose the host in the analytics --- crates/meilisearch/src/routes/export_analytics.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/crates/meilisearch/src/routes/export_analytics.rs b/crates/meilisearch/src/routes/export_analytics.rs index b66a5133b..bf1f667e0 100644 --- a/crates/meilisearch/src/routes/export_analytics.rs +++ b/crates/meilisearch/src/routes/export_analytics.rs @@ -1,3 +1,5 @@ +use url::Url; + use crate::analytics::Aggregate; use crate::routes::export::Export; @@ -5,6 +7,7 @@ use crate::routes::export::Export; pub struct ExportAnalytics { total_received: usize, has_api_key: bool, + hosts: Vec, sum_index_patterns: usize, sum_patterns_with_filter: usize, sum_patterns_with_override_settings: usize, @@ -13,8 +16,10 @@ pub struct ExportAnalytics { impl ExportAnalytics { pub fn from_export(export: &Export) -> Self { - let Export { url: _, api_key, payload_size, indexes } = export; + let Export { url, api_key, payload_size, indexes } = export; + let url = Url::parse(url).ok(); + let host = url.as_ref().and_then(Url::host_str); let has_api_key = api_key.is_some(); let index_patterns_count = indexes.as_ref().map_or(0, |indexes| indexes.len()); let patterns_with_filter_count = indexes.as_ref().map_or(0, |indexes| { @@ -33,6 +38,7 @@ impl ExportAnalytics { Self { total_received: 1, has_api_key, + hosts: host.map(ToOwned::to_owned).map_or_else(Default::default, |h| vec![h]), sum_index_patterns: index_patterns_count, sum_patterns_with_filter: patterns_with_filter_count, sum_patterns_with_override_settings: patterns_with_override_settings_count, @@ -49,6 +55,7 @@ impl Aggregate for ExportAnalytics { fn aggregate(mut self: Box, other: Box) -> Box { self.total_received += other.total_received; self.has_api_key |= other.has_api_key; + self.hosts.extend(other.hosts); self.sum_index_patterns += other.sum_index_patterns; self.sum_patterns_with_filter += other.sum_patterns_with_filter; self.sum_patterns_with_override_settings += other.sum_patterns_with_override_settings; @@ -84,6 +91,7 @@ impl Aggregate for ExportAnalytics { serde_json::json!({ "total_received": self.total_received, "has_api_key": self.has_api_key, + "hosts": self.hosts, "avg_index_patterns": avg_index_patterns, "avg_patterns_with_filter": avg_patterns_with_filter, "avg_patterns_with_override_settings": avg_patterns_with_override_settings, From 4c7a6e5c1bd25114dab164fb0fcfd67403012ea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Mon, 7 Jul 2025 10:59:39 +0200 Subject: [PATCH 2/2] Do not leak private URLs --- .../src/routes/export_analytics.rs | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/crates/meilisearch/src/routes/export_analytics.rs b/crates/meilisearch/src/routes/export_analytics.rs index bf1f667e0..a2f0a129d 100644 --- a/crates/meilisearch/src/routes/export_analytics.rs +++ b/crates/meilisearch/src/routes/export_analytics.rs @@ -7,7 +7,7 @@ use crate::routes::export::Export; pub struct ExportAnalytics { total_received: usize, has_api_key: bool, - hosts: Vec, + sum_exports_meilisearch_cloud: usize, sum_index_patterns: usize, sum_patterns_with_filter: usize, sum_patterns_with_override_settings: usize, @@ -19,7 +19,11 @@ impl ExportAnalytics { let Export { url, api_key, payload_size, indexes } = export; let url = Url::parse(url).ok(); - let host = url.as_ref().and_then(Url::host_str); + let is_meilisearch_cloud = url.as_ref().and_then(Url::host_str).is_some_and(|host| { + host.ends_with("meilisearch.dev") + || host.ends_with("meilisearch.com") + || host.ends_with("meilisearch.io") + }); let has_api_key = api_key.is_some(); let index_patterns_count = indexes.as_ref().map_or(0, |indexes| indexes.len()); let patterns_with_filter_count = indexes.as_ref().map_or(0, |indexes| { @@ -38,7 +42,7 @@ impl ExportAnalytics { Self { total_received: 1, has_api_key, - hosts: host.map(ToOwned::to_owned).map_or_else(Default::default, |h| vec![h]), + sum_exports_meilisearch_cloud: is_meilisearch_cloud as usize, sum_index_patterns: index_patterns_count, sum_patterns_with_filter: patterns_with_filter_count, sum_patterns_with_override_settings: patterns_with_override_settings_count, @@ -55,7 +59,7 @@ impl Aggregate for ExportAnalytics { fn aggregate(mut self: Box, other: Box) -> Box { self.total_received += other.total_received; self.has_api_key |= other.has_api_key; - self.hosts.extend(other.hosts); + self.sum_exports_meilisearch_cloud += other.sum_exports_meilisearch_cloud; self.sum_index_patterns += other.sum_index_patterns; self.sum_patterns_with_filter += other.sum_patterns_with_filter; self.sum_patterns_with_override_settings += other.sum_patterns_with_override_settings; @@ -70,6 +74,12 @@ impl Aggregate for ExportAnalytics { Some(self.payload_sizes.iter().sum::() / self.payload_sizes.len() as u64) }; + let avg_exports_meilisearch_cloud = if self.total_received == 0 { + None + } else { + Some(self.sum_exports_meilisearch_cloud as f64 / self.total_received as f64) + }; + let avg_index_patterns = if self.total_received == 0 { None } else { @@ -91,7 +101,7 @@ impl Aggregate for ExportAnalytics { serde_json::json!({ "total_received": self.total_received, "has_api_key": self.has_api_key, - "hosts": self.hosts, + "avg_exports_meilisearch_cloud": avg_exports_meilisearch_cloud, "avg_index_patterns": avg_index_patterns, "avg_patterns_with_filter": avg_patterns_with_filter, "avg_patterns_with_override_settings": avg_patterns_with_override_settings,