Skip to content

Conversation

@oasisk
Copy link
Contributor

@oasisk oasisk commented Oct 26, 2025

PR Type

Enhancement, Tests


Description

  • Introduce alert deduplication feature

  • Persist dedup state and migration

  • API/UI support for dedup config

  • Scheduled cleanup job added


Diagram Walkthrough

flowchart LR
  Config["Config: DeduplicationConfig + grouping"] -- "exposed in Alert" --> API["HTTP Models: Alert.deduplication"]
  API -- "persist/read" --> Infra["Infra: alerts table cols + dedup_state table"]
  Infra -- "migration + entity" --> DB["DB Schema v11"]
  Scheduler["Scheduler handlers"] -- "apply_deduplication()" --> Service["Service: alerts/deduplication"]
  Service -- "fingerprint + state" --> Infra
  Job["Background job"] -- "cleanup_expired_state" --> Service
  UI["Web UI: form + i18n"] -- "bind Alert.deduplication" --> API
Loading

File Walkthrough

Relevant files
Configuration changes
3 files
config.rs
Bump DB schema version to 11                                                         
+1/-1     
mod.rs
Wire enterprise-only dedup migration                                         
+7/-0     
mod.rs
Gate deduplication module behind enterprise feature           
+2/-0     
Enhancement
15 files
alert.rs
Add optional deduplication to Alert model                               
+4/-1     
mod.rs
Export deduplication module                                                           
+1/-0     
mod.rs
Expose deduplication in HTTP Alert model mappings               
+7/-1     
mod.rs
Map dedup fields to DB and serialize config                           
+29/-0   
alert_dedup_state.rs
New entity for deduplication state                                             
+85/-0   
alerts.rs
Add dedup columns to alerts entity                                             
+3/-0     
mod.rs
Register alert_dedup_state entity                                               
+1/-0     
m20251024_000001_add_alert_deduplication.rs
Migration: add dedup columns and state table                         
+245/-0 
alert_manager.rs
Add scheduled dedup state cleanup job                                       
+55/-0   
deduplication.rs
Implement dedup logic, fingerprinting, cleanup                     
+975/-0 
handlers.rs
Apply deduplication before sending alerts                               
+49/-0   
alert.ts
Add deduplication to Alert interface                                         
+11/-0   
AlertsContainer.vue
UX: expand/collapse area clickable with hover                       
+12/-5   
DeduplicationConfig.vue
New UI for configuring alert deduplication                             
+401/-0 
ScheduledAlert.vue
Integrate dedup config into scheduled alerts (enterprise)
+13/-3   
Tests
1 files
deduplication.rs
New deduplication and grouping config with tests                 
+183/-0 
Documentation
1 files
en.json
i18n strings for deduplication UI                                               
+23/-1   

@github-actions
Copy link
Contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Possible Panic

In dedup config load path, value.dedup_config.unwrap_or_else(...) is used after checking only value.dedup_enabled. If dedup_config contains invalid JSON structure for DeduplicationConfig, serde_json::from_value will error (propagated via ?). Validate or handle deserialization failures to avoid failing alert fetches.

// Load deduplication configuration if enabled
if value.dedup_enabled {
    let dedup_config_json = value.dedup_config.unwrap_or_else(|| serde_json::json!({}));
    let mut dedup_config: MetaDeduplicationConfig =
        serde_json::from_value(dedup_config_json)?;
    dedup_config.enabled = true;
    dedup_config.time_window_minutes = value.dedup_time_window_minutes.map(|v| v as i64);
    alert.deduplication = Some(dedup_config);
}
Control Flow Risk

When all results are deduplicated, function returns early after updating scheduler state. Ensure all expected side-effects (metrics, logs, counters) are still executed; double-check no missed paths like audit/logging or hooks that normally run after notifications.

trigger_data_stream.next_run_at = new_trigger.next_run_at;

if trigger_results.data.is_some() {
    trigger_data.last_satisfied_at = Some(triggered_at);
}

// send notification
if let Some(data) = trigger_results.data {
    // Apply deduplication if enabled (enterprise-only feature)
    #[cfg(feature = "enterprise")]
    let data = if let Some(db) = ORM_CLIENT.get() {
        match crate::service::alerts::deduplication::apply_deduplication(
            db,
            &alert,
            data.clone(),
        )
        .await
        {
            Ok(deduplicated_data) => {
                if deduplicated_data.is_empty() {
                    log::debug!(
                        "[SCHEDULER trace_id {scheduler_trace_id}] All alert results deduplicated for org: {}, module_key: {}",
                        &new_trigger.org,
                        &new_trigger.module_key
                    );
                    // All results were deduplicated, skip notification
                    // Still update the trigger timing
                    trigger_data.period_end_time = if should_store_last_end_time {
                        Some(trigger_results.end_time)
                    } else {
                        None
                    };
                    new_trigger.data = json::to_string(&trigger_data).unwrap();
                    db::scheduler::update_trigger(new_trigger, true, &query_trace_id).await?;
                    publish_triggers_usage(trigger_data_stream).await;
                    return Ok(());
                }
                deduplicated_data
            }
            Err(e) => {
                log::error!(
                    "[SCHEDULER trace_id {scheduler_trace_id}] Error applying deduplication for org: {}, module_key: {}: {}",
                    &new_trigger.org,
                    &new_trigger.module_key,
                    e
                );
                // On error, continue with original data to avoid missing alerts
                data
            }
        }
    } else {
        log::warn!(
            "[SCHEDULER trace_id {scheduler_trace_id}] Could not connect to ORM for deduplication, continuing without it"
        );
        data
    };

    let vars = get_row_column_map(&data);
Index/Length Constraints

alert_dedup_state.fingerprint is defined as string_len(64) and primary key; confirm the SHA-256 hex length assumption matches all implementations. If future changes produce different lengths (e.g., base64), inserts will fail. Consider explicit validation or comments where fingerprints are generated.

/// Creates the alert_dedup_state table
async fn create_alert_dedup_state_table(manager: &SchemaManager<'_>) -> Result<(), DbErr> {
    manager
        .create_table(
            Table::create()
                .table(AlertDedupState::Table)
                .if_not_exists()
                .col(
                    ColumnDef::new(AlertDedupState::Fingerprint)
                        .string_len(64)
                        .not_null()
                        .primary_key(),
                )
                .col(
                    ColumnDef::new(AlertDedupState::AlertId)
                        .char_len(27)
                        .not_null(),
                )
                .col(
                    ColumnDef::new(AlertDedupState::OrgId)
                        .string_len(100)
                        .not_null(),
                )
                .col(
                    ColumnDef::new(AlertDedupState::FirstSeenAt)
                        .big_integer()
                        .not_null(),
                )
                .col(
                    ColumnDef::new(AlertDedupState::LastSeenAt)
                        .big_integer()
                        .not_null(),
                )
                .col(
                    ColumnDef::new(AlertDedupState::OccurrenceCount)
                        .big_integer()
                        .not_null()
                        .default(1),
                )
                .col(
                    ColumnDef::new(AlertDedupState::NotificationSent)
                        .boolean()
                        .not_null()
                        .default(false),
                )
                .col(
                    ColumnDef::new(AlertDedupState::CreatedAt)
                        .big_integer()
                        .not_null(),

@github-actions
Copy link
Contributor

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
General
Remove unnecessary data cloning

Avoid cloning potentially large data upfront; only clone when needed. Also ensure
data is not moved before logging/skip path by referencing slices and cloning on the
send path. This reduces memory overhead and prevents unnecessary allocations under
high alert volumes.

src/service/alerts/scheduler/handlers.rs [611-655]

 let data = if let Some(db) = ORM_CLIENT.get() {
     match crate::service::alerts::deduplication::apply_deduplication(
         db,
         &alert,
-        data.clone(),
+        data, // move ownership into dedup call
     )
     .await
     {
         Ok(deduplicated_data) => {
             if deduplicated_data.is_empty() {
-                log::debug!(...
-                // skip notification
-                ...
+                log::debug!(
+                    "[SCHEDULER trace_id {scheduler_trace_id}] All alert results deduplicated for org: {}, module_key: {}",
+                    &new_trigger.org,
+                    &new_trigger.module_key
+                );
+                // skip notification and update schedule
+                trigger_data.period_end_time = if should_store_last_end_time {
+                    Some(trigger_results.end_time)
+                } else {
+                    None
+                };
+                new_trigger.data = json::to_string(&trigger_data).unwrap();
+                db::scheduler::update_trigger(new_trigger, true, &query_trace_id).await?;
+                publish_triggers_usage(trigger_data_stream).await;
                 return Ok(());
             }
             deduplicated_data
         }
         Err(e) => {
-            log::error!(...
-            // On error, continue with original data to avoid missing alerts
-            data
+            log::error!(
+                "[SCHEDULER trace_id {scheduler_trace_id}] Error applying deduplication for org: {}, module_key: {}: {}",
+                &new_trigger.org,
+                &new_trigger.module_key,
+                e
+            );
+            // On error, proceed without dedup by re-fetching from trigger_results
+            trigger_results.data.unwrap_or_default()
         }
     }
 } else {
-    log::warn!(...
-    data
+    log::warn!(
+        "[SCHEDULER trace_id {scheduler_trace_id}] Could not connect to ORM for deduplication, continuing without it"
+    );
+    trigger_results.data.unwrap_or_default()
 };
Suggestion importance[1-10]: 7

__

Why: Avoiding the upfront clone of data can reduce allocations on large payloads; the improved logic defers cloning and handles empty/dedup cases. It’s a reasonable optimization with clear impact, though care is needed to not reuse moved values.

Medium
Make migration idempotent and ordered

Ensure the new columns exist before creating dependent indexes across all backends.
On MySQL, repeated ALTERs without IF NOT EXISTS can error; add existence checks to
make the migration idempotent. Also wrap each step to gracefully handle
already-present schema pieces to avoid failing on reruns.

src/infra/src/table/migration/m20251024_000001_add_alert_deduplication.rs [31-36]

-// Add deduplication columns to alerts table
+// Add deduplication columns to alerts table (idempotent per backend)
 add_dedup_columns(manager).await?;
 
-// Create alert_dedup_state table
+// Create alert_dedup_state table first to avoid index creation referencing missing objects
 create_alert_dedup_state_table(manager).await?;
 
+// Create index on dedup_enabled for fast filtering (idempotent)
+manager
+    .create_index(
+        Index::create()
+            .if_not_exists()
+            .name("idx_alerts_dedup_enabled")
+            .table(Alerts::Table)
+            .col(Alerts::DedupEnabled)
+            .to_owned(),
+    )
+    .await?;
+
Suggestion importance[1-10]: 3

__

Why: The migration already creates the index idempotently with if_not_exists after add_dedup_columns; MySQL path lacks IF NOT EXISTS but is handled by backend branching. The suggestion is mostly reiterating existing behavior with minor ordering commentary, offering limited improvement.

Low
Possible issue
Prevent potential Tokio deadlock

Avoid calling async code via block_on inside block_in_place; this can deadlock when
executed on a Tokio worker thread. Offload the parsing to a dedicated blocking task
or refactor to be fully async. If synchronous path is required, return None on error
and log a warning rather than potentially stalling the scheduler.

src/service/alerts/deduplication.rs [200-216]

-let sql_parsed = tokio::task::block_in_place(|| {
-    tokio::runtime::Handle::current().block_on(async {
-        crate::service::search::sql::Sql::new(
-            &search_query,
-            &alert.org_id,
-            alert.stream_type,
-            None,
-        )
-        .await
-    })
-});
+// Prefer fully-async usage by requiring an async context to call this helper,
+// or offload to spawn_blocking to avoid deadlocks.
+let sql_parsed = tokio::task::spawn_blocking({
+    let search_query = search_query.clone();
+    let org_id = alert.org_id.clone();
+    let stream_type = alert.stream_type;
+    move || {
+        // Create a new runtime in the blocking thread to avoid blocking current executor
+        let rt = tokio::runtime::Builder::new_current_thread()
+            .enable_all()
+            .build()
+            .map_err(|e| anyhow::anyhow!(e.to_string()))?;
+        rt.block_on(async {
+            crate::service::search::sql::Sql::new(&search_query, &org_id, stream_type, None)
+                .await
+        })
+    }
+})
+.await
+.map_err(|e| anyhow::anyhow!(e.to_string()))?;
Suggestion importance[1-10]: 5

__

Why: The warning about block_in_place + block_on is valid in Tokio contexts, but the proposed fix adds complexity (spawn_blocking + building a runtime) and may not be appropriate inside async code. The concern is moderate; however, correctness of the replacement isn't clearly superior across all runtimes.

Low

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile Overview

Greptile Summary

Implemented comprehensive alert deduplication feature (enterprise-only) with fingerprint-based duplicate detection, time-window tracking, and automatic cleanup.

Key Changes

  • Core deduplication logic (src/service/alerts/deduplication.rs): Fingerprint calculation using SHA-256 hash of alert name, query context, and dimensional fields. Supports auto-detection for SQL (GROUP BY), PromQL (labels), and Custom queries (conditions)
  • Database schema (m20251024_000001_add_alert_deduplication.rs): Added alert_dedup_state table with proper indexes and foreign keys, plus 3 new columns to alerts table
  • Alert scheduler integration (handlers.rs): Deduplication applied before sending notifications, with graceful error handling that falls back to original behavior
  • Background cleanup job (alert_manager.rs): Hourly cleanup of dedup state records older than 24 hours
  • Frontend UI (DeduplicationConfig.vue): User-friendly configuration interface for fingerprint fields, time windows, and grouping options

Issues Found

  • Silent error handling in deduplication state updates: Errors when saving dedup state are ignored using let _ =, which could lead to inconsistent state or duplicate notifications

Confidence Score: 4/5

  • This PR is mostly safe to merge with minor error handling improvements needed
  • The implementation is well-architected with proper enterprise feature gating, comprehensive tests, and correct database schema. However, silent error handling in the deduplication state updates (lines 666-678 and 693-705) could lead to inconsistent state where notifications are sent/suppressed without proper dedup tracking. These errors should be logged at minimum.
  • src/service/alerts/deduplication.rs requires attention for error handling improvements in the apply_deduplication_enterprise function

Important Files Changed

File Analysis

Filename Score Overview
src/service/alerts/deduplication.rs 4/5 Implemented core deduplication logic with fingerprinting, state management, and enterprise feature gating
src/infra/src/table/migration/m20251024_000001_add_alert_deduplication.rs 5/5 Added database migration for deduplication with proper indexes and foreign key constraints
src/job/alert_manager.rs 5/5 Added cleanup job for old deduplication state records with enterprise feature gating
src/service/alerts/scheduler/handlers.rs 4/5 Integrated deduplication into alert trigger handling with proper error handling
src/infra/src/table/alerts/mod.rs 5/5 Updated alert database operations to handle deduplication configuration fields

Sequence Diagram

sequenceDiagram
    participant Scheduler as Alert Scheduler
    participant Handler as Alert Handler
    participant DedupService as Deduplication Service
    participant DB as Database (ORM)
    participant AlertEngine as Alert Engine
    participant Notification as Notification Service

    Scheduler->>Handler: handle_alert_triggers(trigger)
    Handler->>AlertEngine: Execute alert query
    AlertEngine-->>Handler: Return result_rows
    
    alt Deduplication Enabled (Enterprise)
        Handler->>DedupService: apply_deduplication(alert, result_rows)
        
        loop For each result row
            DedupService->>DedupService: calculate_fingerprint(alert, row)
            Note over DedupService: Fingerprint = SHA256(alert_name + query_context + dimensional_fields)
            
            DedupService->>DB: get_dedup_state(fingerprint)
            
            alt State exists and within time window
                DedupService->>DB: save_dedup_state(update occurrence_count)
                Note over DedupService: Suppress notification
            else State expired or doesn't exist
                DedupService->>DB: save_dedup_state(new state)
                Note over DedupService: Allow notification
            end
        end
        
        DedupService-->>Handler: Return deduplicated_rows
        
        alt All rows deduplicated
            Handler->>DB: update_trigger(timing only)
            Note over Handler: Skip notification
        end
    end
    
    Handler->>Notification: send_notification(deduplicated_rows)
    Handler->>DB: update_trigger(complete state)
    
    Note over Scheduler,DB: Background Cleanup Job (Hourly)
    Scheduler->>DedupService: cleanup_expired_state()
    DedupService->>DB: Delete records older than 24 hours
Loading

20 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

oasisk and others added 2 commits October 26, 2025 10:30
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@testdino-playwright-reporter
Copy link

⚠️ Test Run Unstable


Author: oasisk | Branch: feat-alert-dedup | Commit: b13335e

Testdino Test Results

Status Total Passed Failed Skipped Flaky Pass Rate Duration
4 tests failed 365 339 4 19 3 93% 10m 48s

Test Failure Analysis

  1. alerts-ui-operations.spec.js: Multiple timeout issues related to element visibility and clicks
    1. Alerts UI Operations Alert Module UI Validations and Filters Check: Element 'Alert saved successfully.' not found within timeout.
    2. Alerts UI Operations Create and Delete Scheduled Alert with SQL Query: Timeout waiting for 'keyboard_arrow_down' button click.
  2. alerts-import.spec.js: Timeout issue with alert visibility after creation
    1. Alerts Import/Export Import/Export Alert Functionality: 'Alert saved successfully.' not visible after alert creation.
  3. alerts-e2e-flow.spec.js: Consistent timeout on alert creation confirmation
    1. Alerts E2E Flow Alerts E2E Flow - Create, Update, Move, Clone, Delete, Pause, Resume: 'Alert saved successfully.' not visible after alert creation.

Root Cause Analysis

  • The code changes in src/.../alerts/deduplication.rs indicate potential issues with saving alert states, which may affect UI feedback.

Recommended Actions

  1. Investigate the timing and conditions under which 'Alert saved successfully.' appears to ensure it is displayed promptly after alert creation.
  2. Review the click handling for the 'keyboard_arrow_down' element to confirm it is available and visible before attempting to click.
  3. Increase timeout settings for critical UI interactions in alerts-ui-operations.spec.js to accommodate slower responses.

View Detailed Results

@testdino-playwright-reporter
Copy link

⚠️ Test Run Unstable


Author: oasisk | Branch: feat-alert-dedup | Commit: b13335e

Testdino Test Results

Status Total Passed Failed Skipped Flaky Pass Rate Duration
4 tests failed 365 340 4 19 2 93% 10m 47s

Test Failure Analysis

  1. alerts-ui-operations.spec.js: Multiple timeout issues related to element visibility and clicks
    1. Alerts UI Operations Alert Module UI Validations and Filters Check: Timeout waiting for 'Alert saved successfully.' to be visible.
    2. Alerts UI Operations Create and Delete Scheduled Alert with SQL Query: Timeout waiting for 'keyboard_arrow_down' to be clickable.
  2. alerts-import.spec.js: Timeout issue on alert visibility check
    1. Alerts Import/Export Import/Export Alert Functionality: Timeout waiting for 'Alert saved successfully.' to be visible.
  3. alerts-e2e-flow.spec.js: Timeout issue on alert visibility check
    1. Alerts E2E Flow Alerts E2E Flow - Create, Update, Move, Clone, Delete, Pause, Resume: Timeout waiting for 'Alert saved successfully.' to be visible.

Root Cause Analysis

  • The code changes in alertsPage.js indicate potential issues with alert success message rendering, leading to timeouts.

Recommended Actions

  1. Investigate the rendering logic for the success message in alertsPage.js to ensure it appears as expected. 2. Increase the timeout duration for visibility checks in alerts-ui-operations.spec.js if the UI is slow to respond. 3. Ensure that the 'keyboard_arrow_down' element is present and visible before attempting to click in alerts-ui-operations.spec.js.

View Detailed Results

@testdino-playwright-reporter
Copy link

⚠️ Test Run Unstable


Author: oasisk | Branch: feat-alert-dedup | Commit: b13335e

Testdino Test Results

Status Total Passed Failed Skipped Flaky Pass Rate Duration
4 tests failed 365 339 4 19 3 93% 10m 46s

Test Failure Analysis

  1. alerts-ui-operations.spec.js: Timeout issues related to element visibility and clicks
    1. Alerts UI Operations Alert Module UI Validations and Filters Check: Element 'Alert saved successfully.' not found within timeout.
    2. Alerts UI Operations Create and Delete Scheduled Alert with SQL Query: Timeout waiting for 'keyboard_arrow_down' click action.
  2. alerts-import.spec.js: Visibility timeout for alert success message
    1. Alerts Import/Export Import/Export Alert Functionality: 'Alert saved successfully.' not visible after alert creation.
  3. alerts-e2e-flow.spec.js: Visibility timeout for alert success message
    1. Alerts E2E Flow Alerts E2E Flow - Create, Update, Move, Clone, Delete, Pause, Resume: 'Alert saved successfully.' not found after alert operations.

Root Cause Analysis

  • The recent changes in alertsPage.js may have affected the visibility of alert success messages.

Recommended Actions

  1. Investigate the timing of the alert success message display in alertsPage.js to ensure it appears as expected. 2. Review the click action for 'keyboard_arrow_down' in alertsPage.js to confirm the element is present before interaction. 3. Increase the timeout duration for visibility checks in alertsPage.js to accommodate potential delays.

View Detailed Results

@testdino-playwright-reporter
Copy link

⚠️ Test Run Unstable


Author: oasisk | Branch: feat-alert-dedup | Commit: 73ec785

Testdino Test Results

Status Total Passed Failed Skipped Flaky Pass Rate Duration
4 tests failed 365 338 4 19 4 93% 10m 48s

Test Failure Analysis

  1. alerts-ui-operations.spec.js: Multiple timeout issues related to element visibility and clicks
    1. Alerts UI Operations Alert Module UI Validations and Filters Check: Element not found for success message visibility.
    2. Alerts UI Operations Create and Delete Scheduled Alert with SQL Query: Timeout waiting for dropdown click action.
  2. alerts-import.spec.js: Timeout issues on alert success message visibility
    1. Alerts Import/Export Import/Export Alert Functionality: Element not found for success message visibility.
  3. alerts-e2e-flow.spec.js: Timeout issues on alert success message visibility
    1. Alerts E2E Flow Alerts E2E Flow - Create, Update, Move, Clone, Delete, Pause, Resume: Element not found for success message visibility.

Root Cause Analysis

  • The code changes in alerts/deduplication.rs do not directly relate to the timeout issues observed in the UI tests.

Recommended Actions

  1. Increase the timeout duration for visibility checks in alerts-ui-operations.spec.js to accommodate slower responses.
  2. Ensure the success message 'Alert saved successfully.' is correctly rendered before the visibility check in alerts-import.spec.js and alerts-e2e-flow.spec.js.
  3. Verify the presence of the 'keyboard_arrow_down' element in alerts-ui-operations.spec.js before attempting to click.

View Detailed Results

@testdino-playwright-reporter
Copy link

⚠️ Test Run Unstable


Author: oasisk | Branch: feat-alert-dedup | Commit: 50c902c

Testdino Test Results

Status Total Passed Failed Skipped Flaky Pass Rate Duration
4 tests failed 365 340 4 19 2 93% 10m 47s

Test Failure Analysis

  1. alerts-ui-operations.spec.js: Multiple timeout issues related to element visibility and clicks
    1. Alerts UI Operations Alert Module UI Validations and Filters Check: Element 'Alert saved successfully.' not found within timeout.
    2. Alerts UI Operations Create and Delete Scheduled Alert with SQL Query: Timeout waiting for 'keyboard_arrow_down' click.
  2. alerts-import.spec.js: Timeout issue with alert visibility after creation
    1. Alerts Import/Export Import/Export Alert Functionality: 'Alert saved successfully.' not visible after alert creation.
  3. alerts-e2e-flow.spec.js: Visibility timeout for alert success message
    1. Alerts E2E Flow Alerts E2E Flow - Create, Update, Move, Clone, Delete, Pause, Resume: 'Alert saved successfully.' not found after alert creation.

Root Cause Analysis

  • The recent changes in migration files do not directly relate to the timeout issues observed in the tests.

Recommended Actions

  1. Increase the timeout duration in alerts-ui-operations.spec.js to allow more time for elements to appear.
  2. Verify that the success message 'Alert saved successfully.' is correctly rendered in the DOM after alert creation in both alerts-ui-operations.spec.js and alerts-import.spec.js.
  3. Ensure that the element 'keyboard_arrow_down' is present and visible before attempting to click it in alerts-ui-operations.spec.js.

View Detailed Results

@testdino-playwright-reporter
Copy link

Testdino Test Results

Status Total Passed Failed Skipped Flaky Pass Rate Duration
All tests passed 26 23 0 3 0 88% 1m 9s

View Detailed Results

@testdino-playwright-reporter
Copy link

⚠️ Test Run Unstable


Author: oasisk | Branch: feat-alert-dedup | Commit: 74998b7

Testdino Test Results

Status Total Passed Failed Skipped Flaky Pass Rate Duration
All tests passed 365 341 0 19 5 93% 4m 40s

View Detailed Results

oasisk and others added 2 commits October 26, 2025 17:34
When super_cluster is enabled but the system is running in local_mode,
attempting to emit alert events to the super_cluster queue causes a panic
because the queue initialization explicitly rejects local_mode.

This fix adds a check for `!config.common.local_mode` alongside the existing
`config.super_cluster.enabled` check in all alert event emission functions:
- emit_create_event
- emit_update_event
- emit_delete_event
- _emit_delete_all_event

This allows alerts to function properly in test environments and local
deployments where super_cluster is configured but local_mode is true.

Fixes the 500 Internal Server Error in alert creation E2E tests.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
The previous fix incorrectly tried to access local_mode from the
o2-enterprise config's Common struct, but local_mode is actually
part of the openobserve config.

This fix:
- Imports config::get_config() alongside the enterprise get_o2_config()
- Uses oss_config.common.local_mode for the local mode check
- Uses o2_config.super_cluster.enabled for the super cluster check

This properly checks both configs to determine if super_cluster
events should be emitted.
@testdino-playwright-reporter
Copy link

⚠️ Test Run Unstable


Author: oasisk | Branch: feat-alert-dedup | Commit: 58922b4

Testdino Test Results

Status Total Passed Failed Skipped Flaky Pass Rate Duration
1 test failed 288 267 1 16 4 93% 5m 25s

Test Failure Analysis

  1. dashboard.spec.js: Timeout issues during page load state verification
    1. dashboard UI testcases should update the line chart correctly when used camel case in custom sql query: Page load timed out waiting for network to be idle.

Root Cause Analysis

  • The changes in src/.../alerts/alert.rs may have introduced delays affecting the dashboard loading time.

Recommended Actions

  1. Increase the timeout duration in the test to accommodate longer loading times. 2. Investigate the performance of the SQL query used in the test to ensure it executes efficiently. 3. Optimize the dashboard rendering logic to reduce load times.

View Detailed Results

@oasisk oasisk merged commit 001d444 into main Oct 26, 2025
44 of 46 checks passed
@oasisk oasisk deleted the feat-alert-dedup branch October 26, 2025 13:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants