-
Notifications
You must be signed in to change notification settings - Fork 711
fix: alert threshold fixes #8752
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
Conversation
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Summary
This pull request fixes issues with alert threshold handling when creating alerts from dashboard panels. The changes implement comprehensive defensive programming practices and enhance the integration between dashboard visualizations and alerting functionality.The core improvements focus on three main areas:
-
Null/Undefined Safety: Added robust null checks across data processing functions (
getMetricMinMaxValueincolorPalette.tsandconvertPromQLDatafunction) to prevent runtime errors when processing metric data with missing or malformed results. These functions are critical for alert threshold calculations as they process query results that may be incomplete or timeout. -
Dashboard-to-Alert Integration: Enhanced
PanelSchemaRenderer.vuewith new context menu functionality that allows users to right-click on dashboard panels to create alerts. The implementation includes sophisticated SQL query parsing to extract Y-axis column names for accurate threshold comparisons, supporting both query builder and raw SQL formats with regex-based column extraction. -
Threshold Logic Implementation: Modified
AddAlert.vueto properly handle threshold conditions when creating alerts from dashboard panels. The solution dynamically injects HAVING clauses into SQL queries for aggregation-based thresholds and configures PromQL conditions appropriately. The alert trigger system is configured to fire when any row is returned (threshold=1) since the actual value filtering happens within the query itself.
These changes work together to create a seamless workflow where users can visualize data in dashboards and create meaningful alerts based on the displayed metrics. The defensive programming approach ensures the system remains stable even when dealing with incomplete or failed query results, which is essential for production alert systems.
Important Files Changed
Changed Files
| Filename | Score | Overview |
|---|---|---|
| web/src/utils/dashboard/colorPalette.ts | 5/5 | Added defensive filter to prevent null/undefined metrics from causing runtime errors in getMetricMinMaxValue function |
| web/src/utils/dashboard/convertPromQLData.ts | 4/5 | Added comprehensive null/undefined safety checks throughout convertPromQLData function to prevent runtime errors |
| web/src/components/dashboards/PanelSchemaRenderer.vue | 4/5 | Implemented alert creation functionality with context menu system and SQL query column extraction logic |
| web/src/components/alerts/AddAlert.vue | 4/5 | Enhanced threshold-based alert creation with dynamic SQL HAVING clause insertion and PromQL condition handling |
Confidence score: 4/5
- This PR addresses real production issues with alert threshold handling and includes necessary defensive programming practices
- Score reflects the complexity of SQL query manipulation and potential edge cases in different query formats that may not be fully covered
- Pay close attention to the SQL query modification logic in AddAlert.vue, particularly the HAVING clause insertion patterns
Sequence Diagram
sequenceDiagram
participant User
participant PanelSchemaRenderer
participant AlertContextMenu
participant AddAlert
participant AlertsService
participant ScheduledAlert
participant ValidationUtils
participant PayloadUtils
User->>PanelSchemaRenderer: "Right-click on chart data point"
PanelSchemaRenderer->>PanelSchemaRenderer: "onChartContextMenu(event)"
PanelSchemaRenderer->>AlertContextMenu: "Show context menu with threshold options"
User->>AlertContextMenu: "Select condition (above/below) and threshold value"
AlertContextMenu->>PanelSchemaRenderer: "handleCreateAlert(selection)"
PanelSchemaRenderer->>PanelSchemaRenderer: "Prepare panel data with threshold info"
Note over PanelSchemaRenderer: "Extract query, queryType, yAxisColumn, executedQuery"
PanelSchemaRenderer->>AddAlert: "Navigate to alert creation with panelData"
AddAlert->>AddAlert: "loadPanelDataIfPresent()"
Note over AddAlert: "Parse panelData from URL query"
alt SQL Query with Aggregation
AddAlert->>AddAlert: "Set aggregation.having clause with threshold"
Note over AddAlert: "having.value = threshold, having.operator = condition"
else PromQL Query
AddAlert->>AddAlert: "Set promql_condition with threshold"
Note over AddAlert: "promql_condition.value = threshold"
end
AddAlert->>AddAlert: "Set trigger_condition.threshold = 1"
Note over AddAlert: "Fire alert when ANY row is returned"
User->>AddAlert: "Fill additional alert details"
User->>AddAlert: "Submit alert"
AddAlert->>AddAlert: "onSubmit()"
AddAlert->>AddAlert: "validateFormAndNavigateToErrorField()"
alt Scheduled Alert
AddAlert->>ScheduledAlert: "Validate scheduled alert fields"
ScheduledAlert-->>AddAlert: "Validation result"
end
AddAlert->>ValidationUtils: "validateInputs(payload)"
ValidationUtils-->>AddAlert: "Validation result"
AddAlert->>PayloadUtils: "getAlertPayload()"
PayloadUtils-->>AddAlert: "Formatted payload"
AddAlert->>AddAlert: "transformFEToBE(conditions)"
Note over AddAlert: "Transform frontend format to backend format"
alt Update Alert
AddAlert->>AlertsService: "update_by_alert_id(payload)"
else Create Alert
AddAlert->>AlertsService: "create_by_alert_id(payload)"
end
AlertsService-->>AddAlert: "Success/Error response"
AddAlert->>User: "Show success/error notification"
4 files reviewed, 2 comments
| if (sqlLower.includes('having')) { | ||
| // Already has HAVING clause, add our condition with AND | ||
| sqlQuery = sqlQuery.replace(/having\s+/i, `HAVING ${yAxisColumn} ${operator} ${threshold} AND `); | ||
| } else { | ||
| // No HAVING clause yet, add it at the end | ||
| sqlQuery = `${sqlQuery.trim()} HAVING ${yAxisColumn} ${operator} ${threshold}`; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: String interpolation in SQL could be vulnerable to injection. Consider using parameterized queries or proper escaping for yAxisColumn, operator, and threshold values.
Context Used: Context from dashboard - Avoid directly interpolating values into SQL queries; instead, generate parameter placeholders and b... (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: web/src/components/alerts/AddAlert.vue
Line: 1118:1124
Comment:
**logic:** String interpolation in SQL could be vulnerable to injection. Consider using parameterized queries or proper escaping for `yAxisColumn`, `operator`, and `threshold` values.
**Context Used:** Context from `dashboard` - Avoid directly interpolating values into SQL queries; instead, generate parameter placeholders and b... ([source](https://app.greptile.com/review/custom-context?memory=5078ddce-9cb0-4860-a7aa-e4a273809929))
How can I resolve this? If you propose a fix, please make it concise.| const sqlLower = sqlQuery.toLowerCase(); | ||
| if (sqlLower.includes('having')) { | ||
| // Already has HAVING clause, add our condition with AND | ||
| sqlQuery = sqlQuery.replace(/having\s+/i, `HAVING ${yAxisColumn} ${operator} ${threshold} AND `); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: The regex replacement could be fragile - consider using a proper SQL parser for more robust HAVING clause insertion.
Prompt To Fix With AI
This is a comment left during a code review.
Path: web/src/components/alerts/AddAlert.vue
Line: 1120:1120
Comment:
**style:** The regex replacement could be fragile - consider using a proper SQL parser for more robust HAVING clause insertion.
How can I resolve this? If you propose a fix, please make it concise.
PR Code Suggestions ✨Explore these optional code suggestions:
|
560cafd to
cb30bef
Compare
4c45014 to
bb3f041
Compare
bb3f041 to
c0604a7
Compare
PR Type
Bug fix, Enhancement
Description
Add null-safety in PromQL data utils
Improve axis show checks for empty results
Pass executed query and Y-axis column to alerts
Apply thresholds via HAVING/PromQL condition
Diagram Walkthrough
File Walkthrough
colorPalette.ts
Null-safe metric flattening for min/maxweb/src/utils/dashboard/colorPalette.ts
convertPromQLData.ts
Null-safe PromQL series handling and axesweb/src/utils/dashboard/convertPromQLData.ts
AddAlert.vue
Reliable threshold application for alertsweb/src/components/alerts/AddAlert.vue
PanelSchemaRenderer.vue
Provide context for alert threshold creationweb/src/components/dashboards/PanelSchemaRenderer.vue