Skip to content

Conversation

@nikhilsinhaparseable
Copy link
Contributor

@nikhilsinhaparseable nikhilsinhaparseable commented Oct 27, 2025

add structs for daily mttr history
add helper functions in object store to save mttr history

Summary by CodeRabbit

  • New Features
    • Introduced Mean Time To Resolution (MTTR) tracking for alerts with persistent history.
    • Added date-range query support to retrieve historical MTTR data.
  • Bug Fixes / Improvements
    • Improved reliability of MTTR data reads/writes so history is preserved across restarts.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 27, 2025

Walkthrough

Adds MTTR data types and query params, a storage path for MTTR JSON, expands the Metastore trait with get/put MTTR history, and implements persistent read/write of MTTRHistory in the ObjectStore metastore. Also adjusts alert state path format.

Changes

Cohort / File(s) Summary
MTTR data structures
src/alerts/alert_structs.rs
Adds DailyMTTRStats, MTTRHistory, and MTTRQueryParams (derive Debug, Clone, Serialize, Deserialize with camelCase). Implements MetastoreObject for MTTRHistory (object_id "mttr", path via mttr_json_path()).
Metastore trait extension
src/metastore/metastore_traits.rs
Imports MTTRHistory and adds async trait methods get_mttr_history() and put_mttr_history().
ObjectStoreMetastore implementation
src/metastore/metastores/object_store_metastore.rs
Implements get_mttr_history() to read/deserialize MTTR JSON from mttr_json_path() and put_mttr_history() to write the MTTR object to storage. Adds mttr_json_path import.
Storage path utilities
src/storage/object_storage.rs
Removes "parseable" prefix from alert state JSON path construction and adds pub fn mttr_json_path() -> RelativePathBuf returning the alerts MTTR JSON path.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Client
    participant Metastore
    participant ObjectStore
    participant Storage

    Client->>Metastore: get_mttr_history()
    activate Metastore
    Metastore->>ObjectStore: read at mttr_json_path()
    ObjectStore->>Storage: fetch file
    Storage-->>ObjectStore: file / not found
    ObjectStore-->>Metastore: deserialize -> Option<MTTRHistory>
    Metastore-->>Client: Result<Option<MTTRHistory>>
    deactivate Metastore

    Client->>Metastore: put_mttr_history(history)
    activate Metastore
    Metastore->>ObjectStore: write object to history.get_object_path()
    ObjectStore->>Storage: write file
    Storage-->>ObjectStore: success
    ObjectStore-->>Metastore: Result<()>
    Metastore-->>Client: Result<()>
    deactivate Metastore
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Review deserialization error handling in get_mttr_history() (Ok(None) vs. error propagation).
  • Verify mttr_json_path() and updated alert state path formatting for backward compatibility/migration.
  • Confirm MetastoreObject implementation for MTTRHistory uses the correct object_id and path.

Possibly related PRs

Poem

🐰 I hopped through folders, fluffed each line of code,

Saved MTTR in neat rows along the alert road.
Daily stats and queries now snug in a file,
I nibble bytes and hum a joyous compile. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description check ❓ Inconclusive The description is minimal but covers the two main changes. However, it lacks the Fixes reference, testing checklist, and documentation sections required by the repository template. Add issue reference (Fixes #XXXX), complete the testing checklist, and confirm documentation updates or explain why none are needed.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'store mttr history for given date' is clearly related to the main changes, which add MTTR history data structures and storage functionality.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2f2b324 and 06690ed.

📒 Files selected for processing (4)
  • src/alerts/alert_structs.rs (4 hunks)
  • src/metastore/metastore_traits.rs (2 hunks)
  • src/metastore/metastores/object_store_metastore.rs (3 hunks)
  • src/storage/object_storage.rs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/metastore/metastore_traits.rs (1)
src/metastore/metastores/object_store_metastore.rs (2)
  • get_mttr_history (310-323)
  • put_mttr_history (326-329)
src/alerts/alert_structs.rs (2)
src/storage/object_storage.rs (3)
  • alert_json_path (1140-1142)
  • alert_state_json_path (1157-1162)
  • mttr_json_path (1167-1169)
src/metastore/metastore_traits.rs (2)
  • get_object_id (204-204)
  • get_object_path (203-203)
src/metastore/metastores/object_store_metastore.rs (2)
src/metastore/metastore_traits.rs (2)
  • get_mttr_history (84-84)
  • put_mttr_history (85-85)
src/storage/object_storage.rs (1)
  • to_bytes (1082-1086)
⏰ 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: Quest Smoke and Load Tests for Distributed deployments
  • GitHub Check: Quest Smoke and Load Tests for Standalone deployments
  • GitHub Check: Build Default x86_64-pc-windows-msvc
  • GitHub Check: Build Default x86_64-apple-darwin
  • GitHub Check: Build Default x86_64-unknown-linux-gnu
  • GitHub Check: Build Default aarch64-apple-darwin
  • GitHub Check: Build Default aarch64-unknown-linux-gnu
  • GitHub Check: Build Kafka x86_64-unknown-linux-gnu
  • GitHub Check: Build Kafka aarch64-apple-darwin
  • GitHub Check: coverage
🔇 Additional comments (11)
src/storage/object_storage.rs (2)

1155-1155: Documentation correction looks good.

The comment now accurately reflects the actual path format used in the implementation below.


1164-1169: LGTM!

The new mttr_json_path() function follows the established pattern for path helpers and is correctly integrated with the MTTR history storage implementation.

src/metastore/metastore_traits.rs (2)

30-33: LGTM!

The import correctly adds MTTRHistory alongside existing alert-related types, maintaining consistent structure.


83-85: LGTM!

The new MTTR history methods follow the established patterns in the Metastore trait, with get_mttr_history returning Option<MTTRHistory> for safe handling of missing data and put_mttr_history using the trait object pattern consistent with other put methods.

src/metastore/metastores/object_store_metastore.rs (3)

35-38: LGTM!

The import correctly adds MTTRHistory for use in the new metastore method implementations.


116-116: Minor style improvement.

Consolidating to a single line is consistent with similar methods throughout the file.


325-329: LGTM!

The put_mttr_history implementation correctly follows the established pattern by using obj.get_object_path() to retrieve the storage path.

src/alerts/alert_structs.rs (4)

21-21: LGTM!

NaiveDate import is correctly added for use in the DailyMTTRStats struct.


38-38: LGTM!

The mttr_json_path import is correctly added for use in the MTTRHistory implementation of MetastoreObject.


613-638: LGTM!

The new MTTR data structures are well-designed:

  • DailyMTTRStats appropriately uses NaiveDate for date-only storage
  • MTTRHistory provides a clean container for time-series MTTR data
  • MTTRQueryParams uses Option<String> for flexible date filtering from query parameters
  • All structs follow the established serialization patterns with camelCase

805-813: LGTM!

The MetastoreObject implementation for MTTRHistory correctly uses a constant object ID and leverages the mttr_json_path() helper, following the established pattern.

add structs for daily mttr history
add helper functions in object store to save mttr history
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: 0

🧹 Nitpick comments (3)
src/metastore/metastore_traits.rs (1)

83-85: Add documentation for the new MTTR history methods.

The new trait methods lack detailed documentation. Consider adding doc comments explaining:

  • Purpose of MTTR history storage
  • Return value semantics (when None is returned vs error)
  • Expected behavior for put_mttr_history

Example:

/// Get MTTR history from storage
/// 
/// Returns `Ok(None)` if no history exists or if the stored data cannot be deserialized.
/// Returns `Err` only on storage access errors.
async fn get_mttr_history(&self) -> Result<Option<MTTRHistory>, MetastoreError>;

/// Save MTTR history to storage
/// 
/// The object must implement `MetastoreObject` with appropriate path and ID.
async fn put_mttr_history(&self, obj: &dyn MetastoreObject) -> Result<(), MetastoreError>;
src/alerts/alert_structs.rs (1)

708-722: Consider retention policy and date validation for MTTR history.

Two concerns with the current design:

  1. Unbounded growth: MTTRHistory.daily_stats is a Vec with no apparent size limit. Over time, this will grow indefinitely. Consider adding:

    • A retention policy (e.g., keep only last 90 days)
    • Cleanup logic when reading/writing
    • Documentation about expected data lifecycle
  2. String date validation: MTTRQueryParams uses Option<String> for dates without validation. Consider:

    • Validating date format (YYYY-MM-DD) when deserializing
    • Using NaiveDate type instead of String
    • Adding validation at the API boundary

Example for query params:

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MTTRQueryParams {
    #[serde(deserialize_with = "deserialize_optional_date")]
    pub start_date: Option<NaiveDate>,
    #[serde(deserialize_with = "deserialize_optional_date")]
    pub end_date: Option<NaiveDate>,
}
src/metastore/metastores/object_store_metastore.rs (1)

311-325: LGTM: Implementation follows established patterns.

The get_mttr_history method correctly:

  • Uses the mttr_json_path() helper (addressing the previous review comment)
  • Follows the same error handling pattern as get_alert_state_entry
  • Returns None for missing files and deserialization failures

Optional enhancement: Consider logging when deserialization fails to aid debugging corrupted data.

Ok(bytes) => {
    if let Ok(history) = serde_json::from_slice::<MTTRHistory>(&bytes) {
        Ok(Some(history))
    } else {
        warn!("Failed to deserialize MTTR history from storage");
        Ok(None)
    }
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 06690ed and 762ff66.

📒 Files selected for processing (4)
  • src/alerts/alert_structs.rs (4 hunks)
  • src/metastore/metastore_traits.rs (2 hunks)
  • src/metastore/metastores/object_store_metastore.rs (3 hunks)
  • src/storage/object_storage.rs (2 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-09-18T09:52:07.554Z
Learnt from: nikhilsinhaparseable
Repo: parseablehq/parseable PR: 1415
File: src/storage/object_storage.rs:173-177
Timestamp: 2025-09-18T09:52:07.554Z
Learning: In Parseable's upload system (src/storage/object_storage.rs), the update_storage_metrics function can safely use path.metadata().map_err() to fail on local file metadata read failures because parquet validation (validate_uploaded_parquet_file) ensures file integrity before this step, and the system guarantees local staging files remain accessible throughout the upload flow.

Applied to files:

  • src/storage/object_storage.rs
  • src/metastore/metastores/object_store_metastore.rs
📚 Learning: 2025-10-24T11:54:20.269Z
Learnt from: parmesant
Repo: parseablehq/parseable PR: 1449
File: src/metastore/metastores/object_store_metastore.rs:83-98
Timestamp: 2025-10-24T11:54:20.269Z
Learning: In the `get_overviews` method in `src/metastore/metastores/object_store_metastore.rs`, using `.ok()` to convert all storage errors to `None` when fetching overview objects is the intended behavior. This intentionally treats missing files and other errors (network, permissions, etc.) the same way.

Applied to files:

  • src/metastore/metastores/object_store_metastore.rs
📚 Learning: 2025-09-06T04:26:17.191Z
Learnt from: parmesant
Repo: parseablehq/parseable PR: 1424
File: src/enterprise/utils.rs:65-72
Timestamp: 2025-09-06T04:26:17.191Z
Learning: In Parseable's metastore implementation, MetastoreError::to_detail() returns a MetastoreErrorDetail struct (not a string), which contains structured error information including operation, message, stream_name, and other contextual fields. This struct is designed to be boxed in ObjectStorageError::MetastoreError(Box<MetastoreErrorDetail>).

Applied to files:

  • src/alerts/alert_structs.rs
🧬 Code graph analysis (3)
src/metastore/metastores/object_store_metastore.rs (2)
src/storage/object_storage.rs (2)
  • mttr_json_path (1167-1169)
  • to_bytes (1082-1086)
src/metastore/metastore_traits.rs (2)
  • get_mttr_history (84-84)
  • put_mttr_history (85-85)
src/metastore/metastore_traits.rs (1)
src/metastore/metastores/object_store_metastore.rs (2)
  • get_mttr_history (312-325)
  • put_mttr_history (328-331)
src/alerts/alert_structs.rs (2)
src/storage/object_storage.rs (3)
  • alert_json_path (1140-1142)
  • alert_state_json_path (1157-1162)
  • mttr_json_path (1167-1169)
src/metastore/metastore_traits.rs (2)
  • get_object_id (204-204)
  • get_object_path (203-203)
⏰ 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 x86_64-pc-windows-msvc
  • GitHub Check: Build Default aarch64-apple-darwin
  • GitHub Check: Build Default x86_64-apple-darwin
  • GitHub Check: Build Kafka x86_64-unknown-linux-gnu
  • GitHub Check: Quest Smoke and Load Tests for Standalone deployments
  • 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: Quest Smoke and Load Tests for Distributed deployments
🔇 Additional comments (8)
src/storage/object_storage.rs (2)

1155-1155: LGTM: Comment updated to reflect correct path format.

The documentation now correctly shows the path format without the "parseable" prefix.


1164-1169: LGTM: MTTR path helper follows established patterns.

The new mttr_json_path() function is consistent with other path helpers in this module and properly documented.

src/metastore/metastore_traits.rs (1)

30-33: LGTM: Import structure updated correctly.

The addition of MTTRHistory to the imports is necessary for the new trait methods.

src/alerts/alert_structs.rs (3)

21-21: LGTM: Imports added for MTTR functionality.

The new imports (NaiveDate and mttr_json_path) are necessary for the MTTR history implementation.

Also applies to: 39-39


698-706: Verify that NaiveDate is appropriate for daily MTTR stats.

The date field uses NaiveDate which doesn't include timezone information. For daily aggregations, this means:

  • Dates are interpreted in local/server time
  • Cross-timezone comparisons may be ambiguous
  • This is probably acceptable if all MTTR calculations use a consistent reference timezone

Please confirm this is the intended behavior and that MTTR calculations use a consistent timezone reference.


890-898: LGTM: MetastoreObject implementation is correct.

The implementation properly uses the mttr_json_path() helper and follows the established pattern for other metastore objects.

src/metastore/metastores/object_store_metastore.rs (2)

35-37: LGTM: Imports updated correctly for MTTR history support.

The necessary imports have been added following the existing patterns in this module.

Also applies to: 55-55


327-331: LGTM with concurrency caveat.

The put_mttr_history implementation is straightforward and consistent with other metastore operations.

Note on concurrency: Since MTTR history is stored as a single JSON file, concurrent updates could lead to lost data if multiple processes attempt simultaneous read-modify-write operations. This is likely an acceptable risk for MTTR statistics, but consider:

  • Whether MTTR updates are frequent enough to cause conflicts
  • If atomic updates or optimistic locking would be beneficial

This is more of an architectural consideration than an issue with this specific implementation.

@nikhilsinhaparseable nikhilsinhaparseable merged commit 16189eb into parseablehq:main Nov 17, 2025
13 checks passed
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.

1 participant