Skip to content

Updates for counts API #1347

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 3 commits into from
Jun 19, 2025
Merged

Conversation

parmesant
Copy link
Contributor

@parmesant parmesant commented Jun 15, 2025

counts API will also work with applied filters

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

    • Added support for conditional filtering and grouping in count queries, allowing users to filter and group results using custom conditions.
    • Enhanced counts endpoint to accept and process filter conditions for more flexible data queries.
  • Bug Fixes

    • Improved validation and formatting of filter conditions, ensuring correct handling of operators that do or do not require a value.
  • Style

    • Updated response field names to use camelCase for consistency.
  • Documentation

    • Improved error messages and validation feedback for invalid filter conditions.

Copy link
Contributor

coderabbitai bot commented Jun 15, 2025

Walkthrough

The changes introduce conditional filtering and grouping to the counts query functionality. New logic allows SQL-like filter strings to be generated from condition structures, with validation for operator-value consistency. The HTTP handler and related modules are updated to support filter-based queries, returning results in a consistent, JSON-formatted structure.

Changes

File(s) Change Summary
src/alerts/alerts_utils.rs Added get_filter_string to convert Conditions to SQL-like filter strings; refactored match_alert_operator for value handling; implemented Display for NumberOrString.
src/handlers/http/query.rs Updated get_counts to support conditional filtering via SQL query generation; unified JSON response formatting; updated imports.
src/prism/logstream/mod.rs Set conditions to None in CountsRequest initialization.
src/query/mod.rs Added CountConditions struct; extended CountsRequest with optional conditions; added get_df_sql for SQL query generation; updated CountsRecord to derive Deserialize.
src/alerts/mod.rs Made ConditionConfig.value optional; derived PartialEq/Eq for WhereConfigOperator; added validation for operator-value consistency; updated filter message generation.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant HTTP_Handler as get_counts
    participant QueryModule as CountsRequest
    participant AlertsUtils as get_filter_string
    participant DB

    Client->>HTTP_Handler: POST /get_counts (CountsRequest)
    HTTP_Handler->>QueryModule: Parse and validate request
    alt With conditions
        QueryModule->>AlertsUtils: get_filter_string(conditions)
        AlertsUtils-->>QueryModule: SQL WHERE clause string
        QueryModule->>QueryModule: get_df_sql() (build SQL)
        QueryModule->>DB: Execute SQL query
        DB-->>QueryModule: Records
    else Without conditions
        QueryModule->>QueryModule: get_bin_density()
    end
    QueryModule-->>HTTP_Handler: Records as JSON
    HTTP_Handler-->>Client: JSON response (startTime, endTime, count)
Loading

Suggested reviewers

  • nikhilsinhaparseable

Poem

In fields of code where queries grow,
A rabbit hops where filters flow.
With SQL strings and values checked,
Each count and group is now correct.
From ANDs and NULLs to JSON bright,
The data hops into the light!
🐇✨


📜 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 bb6399e and 8077565.

📒 Files selected for processing (5)
  • src/alerts/alerts_utils.rs (3 hunks)
  • src/alerts/mod.rs (4 hunks)
  • src/handlers/http/query.rs (5 hunks)
  • src/prism/logstream/mod.rs (1 hunks)
  • src/query/mod.rs (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/prism/logstream/mod.rs
  • src/handlers/http/query.rs
  • src/query/mod.rs
  • src/alerts/mod.rs
  • src/alerts/alerts_utils.rs
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: Build Default aarch64-unknown-linux-gnu
  • GitHub Check: Build Default x86_64-pc-windows-msvc
  • GitHub Check: Build Default x86_64-unknown-linux-gnu
  • GitHub Check: Build Kafka 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: coverage
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 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 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.

@parmesant parmesant marked this pull request as ready for review June 16, 2025 06:09
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: 3

🧹 Nitpick comments (1)
src/prism/logstream/mod.rs (1)

352-353: Minor: conditions: None repetition

Since most internal callers will want “no conditions”, consider deriving Default for CountsRequest with conditions defaulting to None so this noise can be eliminated.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d017e73 and b33f734.

📒 Files selected for processing (4)
  • src/alerts/alerts_utils.rs (1 hunks)
  • src/handlers/http/query.rs (5 hunks)
  • src/prism/logstream/mod.rs (1 hunks)
  • src/query/mod.rs (5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: Build Kafka aarch64-apple-darwin
  • GitHub Check: Build Default x86_64-pc-windows-msvc
  • GitHub Check: Build Default x86_64-unknown-linux-gnu
  • GitHub Check: Build Default aarch64-apple-darwin
  • GitHub Check: Build Kafka x86_64-unknown-linux-gnu
  • GitHub Check: Build Default x86_64-apple-darwin
  • GitHub Check: Build Default aarch64-unknown-linux-gnu
  • GitHub Check: coverage
  • GitHub Check: Quest Smoke and Load Tests for Standalone deployments
  • GitHub Check: Quest Smoke and Load Tests for Distributed deployments
🔇 Additional comments (2)
src/query/mod.rs (2)

317-324: group_by field is defined but never used

CountConditions exposes a group_by vector, yet no call-site (including get_df_sql) consumes it. Either wire it into the SQL generation or drop the field to avoid a misleading public API.

Would you like guidance on integrating dynamic GROUP BY support?


338-340: CountsRequest now requires manual initialisation of conditions everywhere

Be sure every CountsRequest instantiation (CLI, tests, etc.) sets conditions: None to avoid breaking changes. Consider #[serde(default)] on the new field to maintain backward compatibility with existing payloads.

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

♻️ Duplicate comments (1)
src/handlers/http/query.rs (1)

398-401: Static fields list breaks grouped / projected COUNT queries

The response always hard-codes

"fields": vec!["startTime", "endTime", "count"]

Yet get_df_sql() can emit queries containing GROUP BY columns (or other projections), so the first N columns of every record batch will be missing from the advertised schema. Clients relying on the fields header will mis-align values.

Reuse the header derived from the first JSON record instead:

-            let res = json!({
-                "fields": vec!["startTime", "endTime", "count"],
-                "records": records,
-            });
+            let fields = records
+                .first()
+                .and_then(|v| v.as_object())
+                .map(|m| m.keys().cloned().collect::<Vec<_>>())
+                .unwrap_or_default();
+            let res = json!({
+                "fields": fields,
+                "records": records,
+            });
🧹 Nitpick comments (1)
src/handlers/http/query.rs (1)

383-389: Hard-coding send_null = true & fields = true overrides caller intent

In the SQL branch the generated Query forces send_null and fields to true, ignoring any query-string flags (sendNull, fields) that the client might have supplied. This changes API behaviour silently.

Unless there is a strong reason, forward the user’s original intent:

-            send_null: true,
-            fields: true,
+            send_null: counts_request.send_null,
+            fields: counts_request.fields,
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b33f734 and 899f6fd.

📒 Files selected for processing (3)
  • src/handlers/http/query.rs (5 hunks)
  • src/otel/traces.rs (12 hunks)
  • src/prism/logstream/mod.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/prism/logstream/mod.rs
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • 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-pc-windows-msvc
  • GitHub Check: Build Default x86_64-unknown-linux-gnu
  • 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: Build Kafka aarch64-apple-darwin
  • GitHub Check: Build Default aarch64-unknown-linux-gnu
  • GitHub Check: coverage
🔇 Additional comments (1)
src/otel/traces.rs (1)

356-380: All good – only cosmetic refactor in helper sample_attributes()

The newly-split AnyValue::StringValue lines improve readability without touching logic or semantics.
Nothing else to call out.

@parmesant parmesant force-pushed the counts-api-update branch from 899f6fd to cb70c09 Compare June 16, 2025 11:34
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

♻️ Duplicate comments (1)
src/handlers/http/query.rs (1)

392-404: Static fields vector still wrong & dynamic header discarded

The response continues to hard-code
["start_time", "endTime", "count"], even when the SQL the backend generates may contain GROUP BY columns (or any other projection).
We already flagged this in a previous review; clients will silently drop the additional columns returned by DataFusion.

Re-use the header that is already available from the JSON objects or the fields output of get_records_and_fields.

-            let json_records = record_batches_to_json(&records)?;
-            let records = json_records.into_iter().map(Value::Object).collect_vec();
-
-            let res = json!({
-                "fields": vec!["start_time", "endTime", "count"],
-                "records": records,
-            });
+            let json_records = record_batches_to_json(&records)?;
+            let records = json_records
+                .into_iter()
+                .map(Value::Object)
+                .collect_vec();
+
+            // Derive the real field order from the first record
+            let fields = records
+                .first()
+                .map(|obj| obj.as_object().unwrap().keys().cloned().collect_vec())
+                .unwrap_or_default();
+
+            let res = json!({
+                "fields": fields,
+                "records": records,
+            });

Failing to fix this will break every grouped COUNT request.

🧹 Nitpick comments (1)
src/handlers/http/query.rs (1)

379-390: Avoid hard-wiring send_null/fields; honour caller intent

The new branch unconditionally sets send_null: true and fields: true.
This quietly overrides any flags supplied via query-string parameters, diverging from the behaviour of the non-SQL path and surprising API consumers.

Either propagate the existing URL parameters or expose explicit JSON fields in CountsRequest so that callers stay in control.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 899f6fd and cb70c09.

📒 Files selected for processing (2)
  • src/handlers/http/query.rs (5 hunks)
  • src/otel/traces.rs (12 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/otel/traces.rs
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: coverage
  • GitHub Check: Build Default x86_64-apple-darwin
  • GitHub Check: Build Kafka x86_64-unknown-linux-gnu
  • GitHub Check: Build Default aarch64-apple-darwin
  • GitHub Check: Build Kafka aarch64-apple-darwin
  • GitHub Check: Build Default x86_64-unknown-linux-gnu
  • GitHub Check: Build Default aarch64-unknown-linux-gnu
  • GitHub Check: Build Default x86_64-pc-windows-msvc
  • GitHub Check: Quest Smoke and Load Tests for Standalone deployments
  • GitHub Check: Quest Smoke and Load Tests for Distributed deployments

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

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

346-367: Formatting logic duplicated – extract small helper

generate_filter_message now repeats the “value or no-value” formatting for both operands and again in the single-condition branch. A 3-line helper eliminates the duplication and future drift:

+fn fmt_expr(c: &ConditionConfig) -> String {
+    match &c.value {
+        Some(v) => format!("{} {} {}", c.column, c.operator, v),
+        None => format!("{} {}", c.column, c.operator),
+    }
+}

@@
-                    let expr1_msg = if let Some(val) = &expr1.value {
-                        format!("{} {} {}", expr1.column, expr1.operator, val)
-                    } else {
-                        format!("{} {}", expr1.column, expr1.operator)
-                    };
-                    let expr2_msg = if let Some(val) = &expr2.value {
-                        format!("{} {} {}", expr2.column, expr2.operator, val)
-                    } else {
-                        format!("{} {}", expr2.column, expr2.operator)
-                    };
-
-                    format!("[{} {op} {}]", expr1_msg, expr2_msg)
+                    format!("[{} {op} {}]", fmt_expr(expr1), fmt_expr(expr2))
@@
-                if let Some(val) = &expr.value {
-                    format!("{} {} {}", expr.column, expr.operator, val)
-                } else {
-                    format!("{} {}", expr.column, expr.operator)
-                }
+                fmt_expr(expr)

Cleaner, easier to maintain, and no behavioural change.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between cb70c09 and bb6399e.

📒 Files selected for processing (3)
  • src/alerts/alerts_utils.rs (3 hunks)
  • src/alerts/mod.rs (4 hunks)
  • src/query/mod.rs (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/alerts/alerts_utils.rs
  • src/query/mod.rs
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: coverage
  • GitHub Check: Quest Smoke and Load Tests for Distributed deployments
  • GitHub Check: Quest Smoke and Load Tests for Standalone deployments
  • GitHub Check: Build Kafka x86_64-unknown-linux-gnu
  • GitHub Check: Build Default x86_64-pc-windows-msvc
  • GitHub Check: Build Default aarch64-unknown-linux-gnu
  • GitHub Check: Build Default x86_64-unknown-linux-gnu
  • GitHub Check: Build Default x86_64-apple-darwin
  • GitHub Check: Build Default aarch64-apple-darwin
🔇 Additional comments (2)
src/alerts/mod.rs (2)

223-256: Enum now PartialEq/Eq – solid for value-presence checks

Deriving PartialEq/Eq on WhereConfigOperator enables the new validation logic below without boiler-plate matches! calls or manual implementations. Good call.


326-330: ConditionConfig.value is now Option – audit all call-sites

Changing value to Option<String> is a breaking change. Although generate_filter_message and validate_configs were updated, other helpers (alerts_utils::match_alert_operator, SQL builders, etc.) may still assume Some(v).
Please grep/scan the codebase to ensure every pattern ‑ condition.value.unwrap() or is_some() logic – is revised, or runtime panics will surface.

@parmesant parmesant force-pushed the counts-api-update branch from bb6399e to dfe5191 Compare June 18, 2025 12:42
@parmesant parmesant force-pushed the counts-api-update branch from dfe5191 to 8077565 Compare June 18, 2025 12:42
Copy link
Contributor

@nikhilsinhaparseable nikhilsinhaparseable left a comment

Choose a reason for hiding this comment

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

looks good

@nitisht nitisht merged commit ed4ac71 into parseablehq:main Jun 19, 2025
14 of 15 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Jun 24, 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.

3 participants