fix(notify): improve webhook target diagnostics for env setup (#2810)

This commit is contained in:
houseme
2026-05-06 08:28:46 +08:00
committed by GitHub
parent 26b3aad069
commit e19b0dd997
3 changed files with 37 additions and 4 deletions
+16
View File
@@ -136,6 +136,22 @@ Similarly, you can run the command with podman
podman compose --profile observability up -d podman compose --profile observability up -d
``` ```
Webhook notification quick start (Docker):
```bash
docker run -d --name rustfs -p 9000:9000 \
-e RUSTFS_NOTIFY_ENABLE=true \
-e RUSTFS_NOTIFY_WEBHOOK_ENABLE_PRIMARY=on \
-e RUSTFS_NOTIFY_WEBHOOK_ENDPOINT_PRIMARY=http://<host-ip>:3020/webhook \
-e RUSTFS_NOTIFY_WEBHOOK_QUEUE_DIR_PRIMARY=/tmp/rustfs-events \
rustfs/rustfs:latest
```
Notes:
- `RUSTFS_NOTIFY_ENABLE=true` enables the global notify module switch.
- For ARN `arn:rustfs:sqs::primary:webhook`, use instance-scoped env vars with `_PRIMARY`.
- If queue dir is omitted, default is `/opt/rustfs/events`; ensure it is writable by the container runtime user.
**NOTE**: We recommend reviewing the `docker-compose.yml` file before running. It defines several services including Grafana, Prometheus, and Jaeger, which are helpful for RustFS observability. If you wish to start Redis or Nginx containers, you can specify the corresponding profiles. **NOTE**: We recommend reviewing the `docker-compose.yml` file before running. It defines several services including Grafana, Prometheus, and Jaeger, which are helpful for RustFS observability. If you wish to start Redis or Nginx containers, you can specify the corresponding profiles.
### 3\. Build from Source (Option 3) - Advanced Users ### 3\. Build from Source (Option 3) - Advanced Users
+19 -3
View File
@@ -24,9 +24,11 @@ use crate::{
}; };
use hashbrown::HashMap; use hashbrown::HashMap;
use rustfs_config::notify::{ use rustfs_config::notify::{
DEFAULT_NOTIFY_TARGET_STREAM_CONCURRENCY, ENV_NOTIFY_TARGET_STREAM_CONCURRENCY, NOTIFY_KAFKA_SUB_SYS, NOTIFY_MQTT_SUB_SYS, DEFAULT_NOTIFY_TARGET_STREAM_CONCURRENCY, ENV_NOTIFY_TARGET_STREAM_CONCURRENCY, ENV_NOTIFY_WEBHOOK_ENABLE,
NOTIFY_NATS_SUB_SYS, NOTIFY_PULSAR_SUB_SYS, NOTIFY_WEBHOOK_SUB_SYS, ENV_NOTIFY_WEBHOOK_ENDPOINT, NOTIFY_KAFKA_SUB_SYS, NOTIFY_MQTT_SUB_SYS, NOTIFY_NATS_SUB_SYS, NOTIFY_PULSAR_SUB_SYS,
NOTIFY_WEBHOOK_SUB_SYS,
}; };
use rustfs_config::{ENV_NOTIFY_ENABLE, EVENT_DEFAULT_DIR};
use rustfs_ecstore::config::{Config, KVS}; use rustfs_ecstore::config::{Config, KVS};
use rustfs_s3_common::EventName; use rustfs_s3_common::EventName;
use rustfs_targets::arn::TargetID; use rustfs_targets::arn::TargetID;
@@ -42,6 +44,14 @@ use tracing::{debug, info, warn};
const MAX_RECENT_LIVE_EVENTS: usize = 1024; const MAX_RECENT_LIVE_EVENTS: usize = 1024;
fn notify_configuration_hint() -> String {
let webhook_enable_primary = format!("{ENV_NOTIFY_WEBHOOK_ENABLE}_PRIMARY");
let webhook_endpoint_primary = format!("{ENV_NOTIFY_WEBHOOK_ENDPOINT}_PRIMARY");
format!(
"No notify targets configured. Check {ENV_NOTIFY_ENABLE}=true and instance-scoped target env vars (for example {webhook_enable_primary} + {webhook_endpoint_primary} for arn:rustfs:sqs::primary:webhook). If using default queue_dir, ensure {EVENT_DEFAULT_DIR} is writable."
)
}
fn subsystem_target_type(target_type: &str) -> &str { fn subsystem_target_type(target_type: &str) -> &str {
match target_type { match target_type {
NOTIFY_WEBHOOK_SUB_SYS => "webhook", NOTIFY_WEBHOOK_SUB_SYS => "webhook",
@@ -325,6 +335,9 @@ impl NotificationSystem {
let targets: Vec<Box<dyn Target<Event> + Send + Sync>> = self.registry.create_targets_from_config(&config).await?; let targets: Vec<Box<dyn Target<Event> + Send + Sync>> = self.registry.create_targets_from_config(&config).await?;
info!("{} notification targets were created", targets.len()); info!("{} notification targets were created", targets.len());
if targets.is_empty() {
warn!("{}", notify_configuration_hint());
}
// Initialize targets and start event streams // Initialize targets and start event streams
let cancellers = self.init_targets_and_start_streams(&targets).await; let cancellers = self.init_targets_and_start_streams(&targets).await;
@@ -586,6 +599,9 @@ impl NotificationSystem {
.map_err(NotificationError::Target)?; .map_err(NotificationError::Target)?;
info!("{} notification targets were created from the new configuration", targets.len()); info!("{} notification targets were created from the new configuration", targets.len());
if targets.is_empty() {
warn!("{}", notify_configuration_hint());
}
// Initialize targets and start event streams using shared helper // Initialize targets and start event streams using shared helper
let new_cancellers = self.init_targets_and_start_streams(&targets).await; let new_cancellers = self.init_targets_and_start_streams(&targets).await;
@@ -607,7 +623,7 @@ impl NotificationSystem {
) -> Result<(), NotificationError> { ) -> Result<(), NotificationError> {
let arn_list = self.notifier.get_arn_list(&cfg.region).await; let arn_list = self.notifier.get_arn_list(&cfg.region).await;
if arn_list.is_empty() { if arn_list.is_empty() {
return Err(NotificationError::Configuration("No targets configured".to_string())); return Err(NotificationError::Configuration(notify_configuration_hint()));
} }
info!("Available ARNs: {:?}", arn_list); info!("Available ARNs: {:?}", arn_list);
// Validate the configuration against the available ARNs // Validate the configuration against the available ARNs
+2 -1
View File
@@ -107,7 +107,8 @@ pub async fn init_event_notifier() {
if !enabled { if !enabled {
info!( info!(
target: "rustfs::main::init_event_notifier", target: "rustfs::main::init_event_notifier",
"Notify module is disabled, event notifier initialization is skipped. Enable the notify module first." "Notify module is disabled, event notifier initialization is skipped. Set {}=true to enable notify initialization.",
rustfs_config::ENV_NOTIFY_ENABLE
); );
return; return;
} }