Skip to content

Modularize Alerts #1390

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 29, 2025
Merged

Conversation

parmesant
Copy link
Contributor

@parmesant parmesant commented Jul 28, 2025

New traits-

  • AlertTrait: A trait describing alerts in Parseable
  • AlertManagerTrait: A trait describing the methods for in-memory alerts structure

New structs-

  • ThresholdAlert: A struct describing threshold type alerts

Fixes #XXXX.

Description


This PR has:

  • been tested to ensure log ingestion and log query works.
  • added comments explaining the "why" and the intent of the code wherever would not be obvious for an unfamiliar reader.
  • added documentation for new or modified features or behaviors.

Summary by CodeRabbit

  • New Features

    • Introduced a trait-based alert management system, enabling dynamic support for multiple alert types and improved extensibility.
    • Added support for threshold-based alerts with configurable evaluation and notification settings.
    • Extended alert types to include "Anomaly" (currently restricted to enterprise mode).
  • Refactor

    • Refactored alert evaluation, management, and HTTP handlers to use trait objects for alerts, improving modularity and code maintainability.
    • Enhanced concurrency control and error handling for alert management operations.
    • Updated alert query execution and validation to improve accuracy and flexibility.
    • Improved safe concurrent access to global alert manager across modules.
  • Bug Fixes

    • Improved thread safety and error reporting when accessing the alert manager, ensuring reliable alert operations.
    • Fixed duplicated route registration in alert-related HTTP endpoints.
  • Chores

    • Re-exported the datafusion crate for easier access by users of this library.

New traits-
- `AlertTrait`: A trait describing alerts in Parseable
- `AlertManagerTrait`: A trait describing the methods for in-memory alerts structure

New structs-
- `ThresholdAlert`: A struct describing threshold type alerts
Copy link
Contributor

coderabbitai bot commented Jul 28, 2025

Walkthrough

This set of changes introduces a trait-based abstraction for alert management, defining AlertTrait and AlertManagerTrait for polymorphic alert operations. A new ThresholdAlert struct is implemented, and the alert storage, evaluation, and HTTP handlers are refactored to operate on trait objects. The global alert manager is now guarded with async locks, and error handling for absent managers is added. Query evaluation and validation are updated to support the new model.

Changes

Cohort / File(s) Change Summary
Alert Trait & Manager Abstractions
src/alerts/traits.rs
Introduces AlertTrait and AlertManagerTrait as async traits defining the contract for alert evaluation, validation, metadata access, cloning, and alert lifecycle management.
ThresholdAlert Implementation
src/alerts/alert_types.rs
Adds ThresholdAlert struct representing threshold-based alerts, implements AlertTrait with async evaluation and validation, conversion to/from AlertConfig, and state mutation.
Alert Utilities Refactor
src/alerts/alerts_utils.rs
Refactors alert evaluation and query execution to operate on AlertTrait trait objects. Updates function signatures, decouples query execution from alert config, and improves JSON result parsing. Enhances error handling for absent alert manager.
Alert Manager Refactor & Global State
src/alerts/mod.rs
Refactors global alert manager to use async trait object with lock. Updates Alerts struct to store boxed trait objects. Implements AlertManagerTrait for Alerts. Adds support for new alert type (Anomaly). Refactors alert loading, updating, state management, and validation to use traits and async concurrency. Updates error handling and query aggregate validation.
Target Handling & Alert Manager Checks
src/alerts/target.rs
Updates target deletion and timeout task logic to acquire locks on the alert manager and check for its presence before accessing alert data, replacing direct access to global alerts.
HTTP Alert Handlers Refactor
src/handlers/http/alerts.rs
Refactors all HTTP alert handlers to operate on trait objects, acquiring locks and checking for alert manager presence. Converts between trait objects and configs for serialization, and updates alert creation, validation, state updates, and deletion accordingly.
Modal Initialization
src/handlers/http/modal/mod.rs
Changes alert loading on initialization to use async getter and lock on alert manager, with error handling for absence.
HTTP Server Route Cleanup
src/handlers/http/modal/server.rs
Removes duplicate registration of the /alerts/list_tags GET route.
Prism Home Alert Titles
src/prism/home/mod.rs
Updates alert title retrieval to acquire async read lock on alert manager and handle absence with error.
Alert Runtime Refactor
src/sync.rs
Updates alert runtime to use trait methods and boxed cloning for alert tasks, reflecting trait-based polymorphism.
Datafusion Re-export
src/lib.rs
Adds public re-export of datafusion crate.

Sequence Diagram(s)

sequenceDiagram
    participant HTTP Handler
    participant AlertManager (trait object)
    participant Alert (trait object)
    participant QueryExecutor

    HTTP Handler->>AlertManager: get_alert_by_id(id)
    AlertManager-->>HTTP Handler: Box<dyn AlertTrait>
    HTTP Handler->>Alert: eval_alert()
    Alert->>QueryExecutor: execute_alert_query(query, time_range)
    QueryExecutor-->>Alert: f64 result
    Alert-->>HTTP Handler: (bool, f64) evaluation result
    HTTP Handler->>AlertManager: update_state(id, new_state, trigger_notif)
    AlertManager-->>HTTP Handler: Result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • chore: simplify alert creation and evaluation #1388: The main PR introduces a new ThresholdAlert struct implementing the AlertTrait with async evaluation and validation based on a query and threshold config, while the retrieved PR simplifies alert creation and evaluation by replacing stream and aggregate configs with a query and threshold config in the alert request and refactors alert evaluation to execute the alert query directly and compare against a threshold; thus, both PRs are directly related as they modify the alert evaluation and configuration to use a query-and-threshold model and implement trait-based alert evaluation accordingly.

  • update: add tags, created to alerts #1389: The main PR introduces a new ThresholdAlert struct implementing the AlertTrait with fields including tags and created timestamps, and refactors alert management to use trait objects, while the retrieved PR adds tags and created fields to the existing AlertConfig struct and supports filtering alerts by tags; thus, both PRs modify alert metadata fields related to tags and creation time but operate on different alert representations (ThresholdAlert trait object vs. AlertConfig struct), making their changes related but complementary rather than overlapping on the same code entities.

Suggested labels

for next release

Suggested reviewers

  • parmesant

Poem

In the warren of code, alerts now hop,
With traits and locks, they never stop.
Thresholds checked with careful might,
Managers guarded through the night.
Queries run and tags in tow,
This bunny’s proud to see it grow!
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2cfd329 and 3e2b749.

📒 Files selected for processing (1)
  • src/alerts/mod.rs (27 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/alerts/mod.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: coverage
  • GitHub Check: Build Default aarch64-apple-darwin
  • GitHub Check: Build Default x86_64-pc-windows-msvc
  • GitHub Check: Build Default x86_64-apple-darwin
  • GitHub Check: Quest Smoke and Load Tests for Standalone deployments
  • GitHub Check: Build Default x86_64-unknown-linux-gnu
  • GitHub Check: Quest Smoke and Load Tests for Distributed deployments
  • GitHub Check: Build Kafka x86_64-unknown-linux-gnu
  • GitHub Check: Build Kafka aarch64-apple-darwin
  • GitHub Check: Build Default aarch64-unknown-linux-gnu
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

♻️ Duplicate comments (1)
src/alerts/mod.rs (1)

518-527: Apply the same error handling improvement here.

This has the same issue as the previous state update - silently ignoring when alert manager is not initialized.

🧹 Nitpick comments (2)
src/alerts/mod.rs (2)

28-28: Remove commented code instead of leaving it in.

Dead code should be removed rather than commented out. Version control preserves the history if needed.

-// use once_cell::sync::Lazy;

103-113: Remove large blocks of commented code.

This commented code should be removed. Version control preserves the history.

-// pub static ALERTS: Lazy<Alerts> = Lazy::new(|| {
-//     let (tx, rx) = mpsc::channel::<AlertTask>(10);
-//     let alerts = Alerts {
-//         alerts: RwLock::new(HashMap::new()),
-//         sender: tx,
-//     };
-
-//     thread::spawn(|| alert_runtime(rx));
-
-//     alerts
-// });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc29387 and 556c37e.

📒 Files selected for processing (11)
  • src/alerts/alert_types.rs (1 hunks)
  • src/alerts/alerts_utils.rs (8 hunks)
  • src/alerts/mod.rs (23 hunks)
  • src/alerts/target.rs (3 hunks)
  • src/alerts/traits.rs (1 hunks)
  • src/handlers/http/alerts.rs (7 hunks)
  • src/handlers/http/modal/mod.rs (2 hunks)
  • src/handlers/http/modal/server.rs (1 hunks)
  • src/lib.rs (1 hunks)
  • src/prism/home/mod.rs (1 hunks)
  • src/sync.rs (1 hunks)
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: de-sh
PR: parseablehq/parseable#0
File: :0-0
Timestamp: 2025-03-20T15:50:45.435Z
Learning: Pay close attention to code comments for typos and semantic clarity during reviews for the Parseable project.
src/handlers/http/modal/server.rs (1)

Learnt from: nikhilsinhaparseable
PR: #1305
File: src/handlers/http/users/dashboards.rs:0-0
Timestamp: 2025-05-01T10:27:56.858Z
Learning: The add_tile() function in src/handlers/http/users/dashboards.rs should use get_dashboard_by_user(dashboard_id, &user_id) instead of get_dashboard(dashboard_id) to ensure proper authorization checks when modifying a dashboard.

src/sync.rs (1)

Learnt from: nikhilsinhaparseable
PR: #1388
File: src/alerts/mod.rs:88-104
Timestamp: 2025-07-24T11:09:21.781Z
Learning: In the Parseable alert system (src/alerts/mod.rs), alert versions are server-generated and controlled via CURRENT_ALERTS_VERSION constant, not user input. The AlertVerison enum's From<&str> implementation correctly defaults unknown versions to V2 since the server only generates known versions (v1, v2). Unknown versions would only occur in exceptional cases like file corruption, making the current fallback approach appropriate.

src/alerts/target.rs (2)

Learnt from: nikhilsinhaparseable
PR: #1346
File: src/sync.rs:78-83
Timestamp: 2025-06-16T04:56:21.613Z
Learning: In Rust async code, #[tokio::main] is appropriate when functions are called from separate OS threads (like thread::spawn()), as it creates a new Tokio runtime for that thread. The "Cannot start a runtime from within a runtime" error only occurs when #[tokio::main] functions are called from within an existing Tokio runtime context.

Learnt from: nikhilsinhaparseable
PR: #1388
File: src/alerts/mod.rs:88-104
Timestamp: 2025-07-24T11:09:21.781Z
Learning: In the Parseable alert system (src/alerts/mod.rs), alert versions are server-generated and controlled via CURRENT_ALERTS_VERSION constant, not user input. The AlertVerison enum's From<&str> implementation correctly defaults unknown versions to V2 since the server only generates known versions (v1, v2). Unknown versions would only occur in exceptional cases like file corruption, making the current fallback approach appropriate.

src/prism/home/mod.rs (1)

Learnt from: nikhilsinhaparseable
PR: #1388
File: src/alerts/mod.rs:88-104
Timestamp: 2025-07-24T11:09:21.781Z
Learning: In the Parseable alert system (src/alerts/mod.rs), alert versions are server-generated and controlled via CURRENT_ALERTS_VERSION constant, not user input. The AlertVerison enum's From<&str> implementation correctly defaults unknown versions to V2 since the server only generates known versions (v1, v2). Unknown versions would only occur in exceptional cases like file corruption, making the current fallback approach appropriate.

src/handlers/http/modal/mod.rs (1)

Learnt from: nikhilsinhaparseable
PR: #1388
File: src/alerts/mod.rs:88-104
Timestamp: 2025-07-24T11:09:21.781Z
Learning: In the Parseable alert system (src/alerts/mod.rs), alert versions are server-generated and controlled via CURRENT_ALERTS_VERSION constant, not user input. The AlertVerison enum's From<&str> implementation correctly defaults unknown versions to V2 since the server only generates known versions (v1, v2). Unknown versions would only occur in exceptional cases like file corruption, making the current fallback approach appropriate.

src/alerts/alert_types.rs (1)

Learnt from: nikhilsinhaparseable
PR: #1388
File: src/alerts/mod.rs:88-104
Timestamp: 2025-07-24T11:09:21.781Z
Learning: In the Parseable alert system (src/alerts/mod.rs), alert versions are server-generated and controlled via CURRENT_ALERTS_VERSION constant, not user input. The AlertVerison enum's From<&str> implementation correctly defaults unknown versions to V2 since the server only generates known versions (v1, v2). Unknown versions would only occur in exceptional cases like file corruption, making the current fallback approach appropriate.

src/alerts/traits.rs (1)

Learnt from: nikhilsinhaparseable
PR: #1388
File: src/alerts/mod.rs:88-104
Timestamp: 2025-07-24T11:09:21.781Z
Learning: In the Parseable alert system (src/alerts/mod.rs), alert versions are server-generated and controlled via CURRENT_ALERTS_VERSION constant, not user input. The AlertVerison enum's From<&str> implementation correctly defaults unknown versions to V2 since the server only generates known versions (v1, v2). Unknown versions would only occur in exceptional cases like file corruption, making the current fallback approach appropriate.

src/handlers/http/alerts.rs (3)

Learnt from: nikhilsinhaparseable
PR: #1388
File: src/alerts/mod.rs:88-104
Timestamp: 2025-07-24T11:09:21.781Z
Learning: In the Parseable alert system (src/alerts/mod.rs), alert versions are server-generated and controlled via CURRENT_ALERTS_VERSION constant, not user input. The AlertVerison enum's From<&str> implementation correctly defaults unknown versions to V2 since the server only generates known versions (v1, v2). Unknown versions would only occur in exceptional cases like file corruption, making the current fallback approach appropriate.

Learnt from: nikhilsinhaparseable
PR: #1346
File: src/handlers/http/health_check.rs:81-90
Timestamp: 2025-06-16T02:04:58.990Z
Learning: In the shutdown function in src/handlers/http/health_check.rs, the design approach is to log errors from sync operations rather than propagate them. This is intentional because the shutdown function is called on SIGTERM/SIGINT signals, and the goal is to perform best-effort cleanup (syncing pending files to object storage) while allowing the shutdown to proceed regardless of sync failures. Logging provides debugging information without blocking the shutdown process.

Learnt from: nikhilsinhaparseable
PR: #1340
File: src/query/mod.rs:64-66
Timestamp: 2025-06-18T06:39:04.775Z
Learning: In src/query/mod.rs, QUERY_SESSION_STATE and QUERY_SESSION serve different architectural purposes: QUERY_SESSION_STATE is used for stats calculation and allows dynamic registration of individual parquet files from the staging path (files created every minute), while QUERY_SESSION is used for object store queries with the global schema provider. Session contexts with schema providers don't support registering individual tables/parquets, so both session objects are necessary for their respective use cases.

src/alerts/alerts_utils.rs (1)

Learnt from: nikhilsinhaparseable
PR: #1388
File: src/alerts/mod.rs:88-104
Timestamp: 2025-07-24T11:09:21.781Z
Learning: In the Parseable alert system (src/alerts/mod.rs), alert versions are server-generated and controlled via CURRENT_ALERTS_VERSION constant, not user input. The AlertVerison enum's From<&str> implementation correctly defaults unknown versions to V2 since the server only generates known versions (v1, v2). Unknown versions would only occur in exceptional cases like file corruption, making the current fallback approach appropriate.

src/alerts/mod.rs (3)

Learnt from: nikhilsinhaparseable
PR: #1388
File: src/alerts/mod.rs:88-104
Timestamp: 2025-07-24T11:09:21.781Z
Learning: In the Parseable alert system (src/alerts/mod.rs), alert versions are server-generated and controlled via CURRENT_ALERTS_VERSION constant, not user input. The AlertVerison enum's From<&str> implementation correctly defaults unknown versions to V2 since the server only generates known versions (v1, v2). Unknown versions would only occur in exceptional cases like file corruption, making the current fallback approach appropriate.

Learnt from: nikhilsinhaparseable
PR: #1340
File: src/storage/object_storage.rs:31-41
Timestamp: 2025-06-18T11:15:10.836Z
Learning: DataFusion's parquet reader defaults to using view types (Utf8View, BinaryView) when reading parquet files via the schema_force_view_types configuration (default: true). This means StringViewArray and BinaryViewArray downcasting is required when processing Arrow arrays from DataFusion parquet operations, even though these types are behind nightly feature flags.

Learnt from: nikhilsinhaparseable
PR: #1340
File: src/query/mod.rs:64-66
Timestamp: 2025-06-18T06:39:04.775Z
Learning: In src/query/mod.rs, QUERY_SESSION_STATE and QUERY_SESSION serve different architectural purposes: QUERY_SESSION_STATE is used for stats calculation and allows dynamic registration of individual parquet files from the staging path (files created every minute), while QUERY_SESSION is used for object store queries with the global schema provider. Session contexts with schema providers don't support registering individual tables/parquets, so both session objects are necessary for their respective use cases.

🧬 Code Graph Analysis (3)
src/handlers/http/modal/server.rs (5)
src/handlers/http/alerts.rs (3)
  • get (117-133)
  • alerts (64-67)
  • list_tags (220-229)
src/alerts/mod.rs (2)
  • alerts (1631-1635)
  • list_tags (1629-1639)
src/alerts/traits.rs (1)
  • list_tags (72-72)
src/handlers/http/users/dashboards.rs (1)
  • list_tags (230-233)
src/users/dashboards.rs (1)
  • list_tags (365-375)
src/sync.rs (3)
src/alerts/alert_types.rs (1)
  • get_id (138-140)
src/alerts/traits.rs (1)
  • get_id (33-33)
src/alerts/alerts_utils.rs (1)
  • evaluate_alert (55-61)
src/alerts/mod.rs (5)
src/handlers/http/mod.rs (1)
  • fetch_schema (92-109)
src/sync.rs (1)
  • alert_runtime (290-350)
src/alerts/alert_types.rs (3)
  • from (213-229)
  • from (233-249)
  • get_state (170-172)
src/alerts/traits.rs (12)
  • load (54-54)
  • list_alerts_for_user (55-59)
  • get_alert_by_id (60-60)
  • update (61-61)
  • update_state (62-67)
  • get_state (41-41)
  • get_state (69-69)
  • delete (68-68)
  • start_task (70-70)
  • delete_task (71-71)
  • list_tags (72-72)
  • get_all_alerts (73-73)
src/utils/mod.rs (1)
  • user_auth_for_query (79-88)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Build Default x86_64-unknown-linux-gnu
  • GitHub Check: Quest Smoke and Load Tests for Standalone deployments
  • GitHub Check: Quest Smoke and Load Tests for Distributed deployments
  • GitHub Check: Build Default x86_64-apple-darwin
  • GitHub Check: Build Default aarch64-unknown-linux-gnu
  • GitHub Check: Build Kafka aarch64-apple-darwin
  • GitHub Check: Build Kafka x86_64-unknown-linux-gnu
  • GitHub Check: Build Default aarch64-apple-darwin
  • GitHub Check: Build Default x86_64-pc-windows-msvc
  • GitHub Check: coverage
🔇 Additional comments (20)
src/lib.rs (1)

55-55: LGTM! Appropriate public re-export for alert system refactor.

The public re-export of datafusion aligns well with the modularization of the alert system, enabling consumers to access DataFusion functionality needed for alert query operations.

src/handlers/http/modal/server.rs (1)

258-264: LGTM! Proper route registration for alert tags listing.

The addition of the /list_tags route under the alerts scope with appropriate authorization aligns with the alert system modularization. The use of Action::ListDashboard for authorization appears consistent with similar listing operations.

src/handlers/http/modal/mod.rs (2)

37-37: LGTM! Proper import for alert manager access.

The addition of get_alert_manager import supports the new trait-based alert manager interface.


186-195: LGTM! Proper async lock handling for alert manager.

The refactored alert loading logic correctly implements the new pattern:

  • Ensures alert manager initialization with get_alert_manager().await
  • Uses proper async lock acquisition with error handling
  • Provides clear error messaging when the alert manager is not set

This approach ensures thread-safe access and proper error handling consistent with the alert system modularization.

src/sync.rs (1)

298-309: LGTM! Proper trait-based alert handling.

The refactored alert runtime correctly adapts to the new trait-based alert system:

  • Uses get_id() method for proper encapsulation
  • Employs clone_box() for trait object cloning
  • Correctly dereferences the ID and passes trait object references to evaluation functions

These changes maintain the same functionality while supporting the new polymorphic alert interface.

src/prism/home/mod.rs (1)

358-366: LGTM! Consistent async lock pattern for alert manager access.

The changes properly implement the new alert manager access pattern:

  • Acquires async read lock for thread-safe access
  • Includes proper error handling when alert manager is not set
  • Maintains the same functionality while supporting the new trait-based interface

This is consistent with the alert system modularization across the codebase.

src/alerts/alert_types.rs (1)

43-210: Well-structured threshold alert implementation!

The ThresholdAlert struct and its AlertTrait implementation are comprehensive and well-designed. The validation logic properly handles mode restrictions, frequency constraints, query validation, and user authorization. The evaluation method correctly delegates to utility functions for query execution and condition evaluation.

src/alerts/traits.rs (1)

29-74: Excellent trait-based abstraction!

The trait design is well-thought-out with clear separation of concerns between AlertTrait (individual alert behavior) and AlertManagerTrait (alert management). The use of async_trait, appropriate trait bounds (Debug + Send + Sync), and the clone_box pattern for trait object cloning demonstrate good Rust practices.

src/alerts/mod.rs (12)

42-49: LGTM! Well-structured module organization.

The new module structure with separate files for traits and alert types promotes better code organization and separation of concerns.


117-123: LGTM! Proper use of trait objects for polymorphism.

The change to store trait objects enables polymorphic alert handling while maintaining type safety through dynamic dispatch.


230-241: LGTM! AlertType extension is well-implemented.

The new Anomaly variant follows the existing naming conventions and display format.


643-643: LGTM! Appropriate use of async.

Converting to async is correct since the method performs async storage operations.


1122-1128: LGTM! Proper feature gating for Anomaly alerts.

The validation correctly restricts Anomaly alerts to Prism mode only.


1177-1177: LGTM! Well-structured query validation refactoring.

The extraction of query validation into standalone functions improves modularity. The recursive logical plan analysis correctly handles nested query structures.

Also applies to: 1289-1325


1365-1366: LGTM! Proper error handling for Arrow operations.

The ArrowError variant is appropriately added with correct HTTP status mapping.

Also applies to: 1390-1390


1401-1495: LGTM! Robust trait implementation with proper error handling.

The implementation correctly:

  • Creates appropriate trait objects based on alert type
  • Provides clear error messaging for enterprise features
  • Includes retry logic for task creation
  • Handles v1 to v2 migration seamlessly

1499-1511: LGTM! Proper use of trait methods.

The implementation correctly uses trait methods to access alert properties in a polymorphic way.


1530-1644: LGTM! Consistent trait method implementations.

All trait methods are properly implemented with correct use of trait object methods and async patterns.


1670-1711: LGTM! Proper error handling and trait usage.

The implementation correctly handles the case when alert manager is not initialized and uses trait methods consistently.


75-87: Potential race condition in lazy initialization.

The current implementation has a TOCTOU (Time-of-Check-Time-of-Use) race condition. Between dropping the read guard and acquiring the write guard, another thread could initialize the manager.

 pub async fn get_alert_manager() -> Arc<dyn AlertManagerTrait> {
     let guard = ALERTS.read().await;
     if let Some(manager) = guard.as_ref() {
         manager.clone()
     } else {
         drop(guard);
         let mut write_guard = ALERTS.write().await;
+        // Re-check after acquiring write lock
         if write_guard.is_none() {
             *write_guard = Some(Arc::new(create_default_alerts_manager()));
         }
         write_guard.as_ref().unwrap().clone()
     }
 }
⛔ Skipped due to learnings
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1388
File: src/alerts/mod.rs:88-104
Timestamp: 2025-07-24T11:09:21.781Z
Learning: In the Parseable alert system (src/alerts/mod.rs), alert versions are server-generated and controlled via CURRENT_ALERTS_VERSION constant, not user input. The AlertVerison enum's From<&str> implementation correctly defaults unknown versions to V2 since the server only generates known versions (v1, v2). Unknown versions would only occur in exceptional cases like file corruption, making the current fallback approach appropriate.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (2)
src/alerts/target.rs (2)

104-109: LGTM! Read lock usage is appropriate for this read-only operation.

The implementation correctly uses a read lock to access the alert manager when only checking if targets are in use, which allows for better concurrency. The error handling for missing alert manager is also appropriate.


292-299: LGTM! Proper error handling replaces the previous panic.

The implementation now handles the missing AlertManager case gracefully by logging an error, resetting the timeout state, and returning early instead of panicking. This prevents the spawned task from silently failing and maintains system consistency.

🧹 Nitpick comments (3)
src/alerts/alert_types.rs (3)

55-57: Clarify the comment about alert state

The comment "for new alerts, state should be resolved" is ambiguous. Consider clarifying what "resolved" means in this context.

-    // for new alerts, state should be resolved
+    // for new alerts, state defaults to AlertState::Resolved

106-106: Potential precision issue with float comparison

Using gt() for float comparison could lead to precision issues. Consider using a tolerance-based comparison or rethinking the logic.

-                    if (notif_duration.as_secs_f64()).gt(&((eval_frequency * 60) as f64)) {
+                    if notif_duration.as_secs() > (eval_frequency * 60) {

108-108: Fix typo in error message

-                            "evalFrequency should be greater than target repetition  interval",
+                            "evalFrequency should be greater than target repetition interval",
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c5344e4 and 8461b69.

📒 Files selected for processing (5)
  • src/alerts/alert_types.rs (1 hunks)
  • src/alerts/alerts_utils.rs (8 hunks)
  • src/alerts/mod.rs (24 hunks)
  • src/alerts/target.rs (3 hunks)
  • src/handlers/http/alerts.rs (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/alerts/alerts_utils.rs
  • src/handlers/http/alerts.rs
  • src/alerts/mod.rs
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: de-sh
PR: parseablehq/parseable#0
File: :0-0
Timestamp: 2025-03-20T15:50:45.435Z
Learning: Pay close attention to code comments for typos and semantic clarity during reviews for the Parseable project.
src/alerts/target.rs (4)

Learnt from: nikhilsinhaparseable
PR: #1346
File: src/handlers/http/health_check.rs:81-90
Timestamp: 2025-06-16T02:04:58.990Z
Learning: In the shutdown function in src/handlers/http/health_check.rs, the design approach is to log errors from sync operations rather than propagate them. This is intentional because the shutdown function is called on SIGTERM/SIGINT signals, and the goal is to perform best-effort cleanup (syncing pending files to object storage) while allowing the shutdown to proceed regardless of sync failures. Logging provides debugging information without blocking the shutdown process.

Learnt from: nikhilsinhaparseable
PR: #1288
File: src/handlers/http/modal/mod.rs:279-301
Timestamp: 2025-04-07T13:23:10.092Z
Learning: For critical operations like writing metadata to disk in NodeMetadata::put_on_disk(), it's preferred to let exceptions propagate (using expect/unwrap) rather than trying to recover with fallback mechanisms, as the failure indicates a fundamental system issue that needs immediate attention.

Learnt from: nikhilsinhaparseable
PR: #1346
File: src/sync.rs:78-83
Timestamp: 2025-06-16T04:56:21.613Z
Learning: In Rust async code, #[tokio::main] is appropriate when functions are called from separate OS threads (like thread::spawn()), as it creates a new Tokio runtime for that thread. The "Cannot start a runtime from within a runtime" error only occurs when #[tokio::main] functions are called from within an existing Tokio runtime context.

Learnt from: nikhilsinhaparseable
PR: #1388
File: src/alerts/mod.rs:88-104
Timestamp: 2025-07-24T11:09:21.781Z
Learning: In the Parseable alert system (src/alerts/mod.rs), alert versions are server-generated and controlled via CURRENT_ALERTS_VERSION constant, not user input. The AlertVerison enum's From<&str> implementation correctly defaults unknown versions to V2 since the server only generates known versions (v1, v2). Unknown versions would only occur in exceptional cases like file corruption, making the current fallback approach appropriate.

src/alerts/alert_types.rs (1)

Learnt from: nikhilsinhaparseable
PR: #1388
File: src/alerts/mod.rs:88-104
Timestamp: 2025-07-24T11:09:21.781Z
Learning: In the Parseable alert system (src/alerts/mod.rs), alert versions are server-generated and controlled via CURRENT_ALERTS_VERSION constant, not user input. The AlertVerison enum's From<&str> implementation correctly defaults unknown versions to V2 since the server only generates known versions (v1, v2). Unknown versions would only occur in exceptional cases like file corruption, making the current fallback approach appropriate.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Quest Smoke and Load Tests for Distributed deployments
  • GitHub Check: Quest Smoke and Load Tests for Standalone deployments
🔇 Additional comments (1)
src/alerts/target.rs (1)

302-302: LGTM! Consistent use of acquired alert manager instance.

The code correctly uses the acquired alerts instance instead of accessing the global ALERTS directly, which is consistent with the new trait-based design and maintains proper lock usage.

Also applies to: 320-320

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
src/alerts/alert_types.rs (2)

27-27: Fix typo: AlertVerison should be AlertVersion

-        AlertConfig, AlertError, AlertState, AlertType, AlertVerison, EvalConfig, Severity,
+        AlertConfig, AlertError, AlertState, AlertType, AlertVersion, EvalConfig, Severity,

45-45: Fix typo: AlertVerison should be AlertVersion

-    pub version: AlertVerison,
+    pub version: AlertVersion,
🧹 Nitpick comments (2)
src/alerts/mod.rs (2)

28-28: Remove commented import

The once_cell::sync::Lazy import is no longer used and should be removed.

-// use once_cell::sync::Lazy;

103-113: Remove commented old implementation

The old ALERTS static implementation is no longer needed and should be removed.

-// pub static ALERTS: Lazy<Alerts> = Lazy::new(|| {
-//     let (tx, rx) = mpsc::channel::<AlertTask>(10);
-//     let alerts = Alerts {
-//         alerts: RwLock::new(HashMap::new()),
-//         sender: tx,
-//     };
-
-//     thread::spawn(|| alert_runtime(rx));
-
-//     alerts
-// });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8461b69 and 2cfd329.

📒 Files selected for processing (2)
  • src/alerts/alert_types.rs (1 hunks)
  • src/alerts/mod.rs (27 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: de-sh
PR: parseablehq/parseable#0
File: :0-0
Timestamp: 2025-03-20T15:50:45.435Z
Learning: Pay close attention to code comments for typos and semantic clarity during reviews for the Parseable project.
src/alerts/alert_types.rs (1)

Learnt from: nikhilsinhaparseable
PR: #1388
File: src/alerts/mod.rs:88-104
Timestamp: 2025-07-24T11:09:21.781Z
Learning: In the Parseable alert system (src/alerts/mod.rs), alert versions are server-generated and controlled via CURRENT_ALERTS_VERSION constant, not user input. The AlertVerison enum's From<&str> implementation correctly defaults unknown versions to V2 since the server only generates known versions (v1, v2). Unknown versions would only occur in exceptional cases like file corruption, making the current fallback approach appropriate.

src/alerts/mod.rs (4)

Learnt from: nikhilsinhaparseable
PR: #1388
File: src/alerts/mod.rs:88-104
Timestamp: 2025-07-24T11:09:21.781Z
Learning: In the Parseable alert system (src/alerts/mod.rs), alert versions are server-generated and controlled via CURRENT_ALERTS_VERSION constant, not user input. The AlertVerison enum's From<&str> implementation correctly defaults unknown versions to V2 since the server only generates known versions (v1, v2). Unknown versions would only occur in exceptional cases like file corruption, making the current fallback approach appropriate.

Learnt from: nikhilsinhaparseable
PR: #1340
File: src/storage/object_storage.rs:31-41
Timestamp: 2025-06-18T11:15:10.836Z
Learning: DataFusion's parquet reader defaults to using view types (Utf8View, BinaryView) when reading parquet files via the schema_force_view_types configuration (default: true). This means StringViewArray and BinaryViewArray downcasting is required when processing Arrow arrays from DataFusion parquet operations, even though these types are behind nightly feature flags.

Learnt from: nikhilsinhaparseable
PR: #1340
File: src/query/mod.rs:64-66
Timestamp: 2025-06-18T06:39:04.775Z
Learning: In src/query/mod.rs, QUERY_SESSION_STATE and QUERY_SESSION serve different architectural purposes: QUERY_SESSION_STATE is used for stats calculation and allows dynamic registration of individual parquet files from the staging path (files created every minute), while QUERY_SESSION is used for object store queries with the global schema provider. Session contexts with schema providers don't support registering individual tables/parquets, so both session objects are necessary for their respective use cases.

Learnt from: nikhilsinhaparseable
PR: #1392
File: src/migration/stream_metadata_migration.rs:303-322
Timestamp: 2025-07-28T17:10:39.448Z
Learning: In Parseable's migration system (src/migration/stream_metadata_migration.rs), each migration function updates the metadata to the current latest format using CURRENT_OBJECT_STORE_VERSION and CURRENT_SCHEMA_VERSION constants, rather than producing incremental versions. For example, v5_v6 function produces v7 format output when these constants are set to "v7", not v6 format.

🧬 Code Graph Analysis (1)
src/alerts/mod.rs (6)
src/query/mod.rs (1)
  • serde_json (552-552)
src/handlers/http/mod.rs (1)
  • fetch_schema (92-109)
src/sync.rs (1)
  • alert_runtime (290-350)
src/alerts/alert_types.rs (3)
  • from (213-229)
  • from (233-249)
  • get_state (170-172)
src/alerts/traits.rs (12)
  • load (54-54)
  • list_alerts_for_user (55-59)
  • get_alert_by_id (60-60)
  • update (61-61)
  • update_state (62-67)
  • get_state (41-41)
  • get_state (69-69)
  • delete (68-68)
  • start_task (70-70)
  • delete_task (71-71)
  • list_tags (72-72)
  • get_all_alerts (73-73)
src/utils/mod.rs (1)
  • user_auth_for_query (79-88)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Build Default x86_64-apple-darwin
  • GitHub Check: Build Default x86_64-pc-windows-msvc
  • GitHub Check: Build Default aarch64-apple-darwin
  • GitHub Check: Build Default x86_64-unknown-linux-gnu
  • GitHub Check: Build Default aarch64-unknown-linux-gnu
  • GitHub Check: Build Kafka aarch64-apple-darwin
  • GitHub Check: Build Kafka x86_64-unknown-linux-gnu
  • GitHub Check: Quest Smoke and Load Tests for Distributed deployments
  • GitHub Check: Quest Smoke and Load Tests for Standalone deployments
  • GitHub Check: coverage

@nikhilsinhaparseable nikhilsinhaparseable merged commit b741ce3 into parseablehq:main Jul 29, 2025
13 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Jul 30, 2025
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants