Skip to content
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

feat: multiple alerts matching rules PoC #2727

Merged
merged 31 commits into from
Dec 25, 2024
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
77dacb8
Add temporary groups for alerts which met Rule conditions, but still …
VladimirFilonov Dec 2, 2024
ee1f334
Check that alerts are firing
VladimirFilonov Dec 2, 2024
260ef5e
Fix logging
VladimirFilonov Dec 2, 2024
e0d22ef
Clean up f-strings and unused imports
VladimirFilonov Dec 2, 2024
3363625
WIP: Fixing tests
VladimirFilonov Dec 3, 2024
912ad9a
Switch to last alert and fingerprints
VladimirFilonov Dec 3, 2024
7046365
Fix is_all_alerts_in_status
VladimirFilonov Dec 7, 2024
243b35c
Fix rules creation and update
VladimirFilonov Dec 7, 2024
5484e9d
Fix migrations deps
VladimirFilonov Dec 7, 2024
8df7729
Refactor RulesEngine
VladimirFilonov Dec 7, 2024
074d08d
Add tests for history-based rules
VladimirFilonov Dec 7, 2024
d0ddee0
Add Rule.create_on to UI form
VladimirFilonov Dec 7, 2024
f358558
Use incident candidates instead of separate entity
VladimirFilonov Dec 10, 2024
3b8b93d
Remove empty lines
VladimirFilonov Dec 10, 2024
8a0faa3
Remove unused imports
VladimirFilonov Dec 10, 2024
8d90a91
Add Rule.create_on migration back
VladimirFilonov Dec 10, 2024
38787b3
Default value for Rule.create_on in migration is "any"
VladimirFilonov Dec 10, 2024
2d260a3
Make __update_client_on_incident_change and __run_workflows public
VladimirFilonov Dec 11, 2024
dbc70c8
Send incident events to workflow manager if required
VladimirFilonov Dec 11, 2024
a76ea4b
Fix rebase indentation issue
VladimirFilonov Dec 16, 2024
b6bb671
Fix migrations history
VladimirFilonov Dec 16, 2024
db60ab7
Merge branch 'main' into feature/historical-rules-poc
VladimirFilonov Dec 16, 2024
1bb05c0
Merge branch 'main' into feature/historical-rules-poc
VladimirFilonov Dec 17, 2024
3046854
Merge branch 'main' into feature/historical-rules-poc
VladimirFilonov Dec 23, 2024
7882750
Fix migrations order
VladimirFilonov Dec 23, 2024
14bd966
Merge branch 'main' into feature/historical-rules-poc
VladimirFilonov Dec 23, 2024
c8b293a
Merge branch 'main' into feature/historical-rules-poc
VladimirFilonov Dec 23, 2024
5fc5cd2
Merge branch 'main' into feature/historical-rules-poc
VladimirFilonov Dec 23, 2024
66adcbd
Fix migrations order
VladimirFilonov Dec 23, 2024
5cc1325
Merge branch 'main' into feature/historical-rules-poc
VladimirFilonov Dec 24, 2024
44ce577
Fix migrations order
VladimirFilonov Dec 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions keep-ui/app/(keep)/rules/CorrelationSidebar/CorrelationForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export const CorrelationForm = ({
/>
</span>
</fieldset>
<fieldset className="grid grid-cols-2">
<fieldset className="grid grid-cols-3">
<div className="mr-10">
<label
className="flex items-center text-tremor-default font-medium text-tremor-content-strong"
Expand All @@ -109,7 +109,7 @@ export const CorrelationForm = ({
<Controller
control={control}
name="groupedAttributes"
render={({ field: { value, onChange } }) => (
render={({field: {value, onChange}}) => (
<MultiSelect
className="mt-2"
value={value}
Expand All @@ -126,7 +126,7 @@ export const CorrelationForm = ({
/>
</div>

<div>
<div className="mr-10">
<label
className="flex items-center text-tremor-default font-medium text-tremor-content-strong"
htmlFor="resolveOn"
Expand All @@ -137,7 +137,7 @@ export const CorrelationForm = ({
<Controller
control={control}
name="resolveOn"
render={({ field: { value, onChange } }) => (
render={({field: {value, onChange}}) => (
<Select value={value} onValueChange={onChange} className="mt-2">
<SelectItem value="never">No auto-resolution</SelectItem>
<SelectItem value="all">All alerts resolved</SelectItem>
Expand All @@ -147,13 +147,33 @@ export const CorrelationForm = ({
)}
/>
</div>

<div>
<label
className="flex items-center text-tremor-default font-medium text-tremor-content-strong"
htmlFor="resolveOn"
>
Start incident on{" "}
</label>

<Controller
control={control}
name="createOn"
render={({field: {value, onChange}}) => (
<Select value={value} onValueChange={onChange} className="mt-2">
<SelectItem value="any">Any condition met</SelectItem>
<SelectItem value="all">All conditions met</SelectItem>
</Select>
)}
/>
</div>
</fieldset>

<div className="flex items-center space-x-2">
<Controller
control={control}
name="requireApprove"
render={({ field: { value, onChange } }) => (
render={({field: {value, onChange}}) => (
<Switch
color="orange"
id="requireManualApprove"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export const CorrelationSidebarBody = ({
groupedAttributes,
requireApprove,
resolveOn,
createOn,
} = correlationFormData;

const body = {
Expand All @@ -77,6 +78,7 @@ export const CorrelationSidebarBody = ({
groupingCriteria: alertsFound.length ? groupedAttributes : [],
requireApprove: requireApprove,
resolveOn: resolveOn,
createOn: createOn,
};

try {
Expand Down
1 change: 1 addition & 0 deletions keep-ui/app/(keep)/rules/CorrelationSidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const DEFAULT_CORRELATION_FORM_VALUES: CorrelationFormType = {
groupedAttributes: [],
requireApprove: false,
resolveOn: "never",
createOn: "any",
query: {
combinator: "or",
rules: [
Expand Down
1 change: 1 addition & 0 deletions keep-ui/app/(keep)/rules/CorrelationSidebar/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ export type CorrelationFormType = {
groupedAttributes: string[];
requireApprove: boolean;
resolveOn: "all" | "first" | "last" | "never";
createOn: "any" | "all";
query: RuleGroupType;
};
1 change: 1 addition & 0 deletions keep-ui/app/(keep)/rules/CorrelationTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export const CorrelationTable = ({ rules }: CorrelationTableProps) => {
groupedAttributes: selectedRule.grouping_criteria,
requireApprove: selectedRule.require_approve,
resolveOn: selectedRule.resolve_on,
createOn: selectedRule.create_on,
query: queryInGroup,
incidents: selectedRule.incidents,
};
Expand Down
1 change: 1 addition & 0 deletions keep-ui/utils/hooks/useRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export type Rule = {
update_time: string | null;
require_approve: boolean;
resolve_on: "all" | "first" | "last" | "never";
create_on: "any" | "all";
distribution: { [group: string]: { [timestamp: string]: number } };
incidents: number;
};
Expand Down
42 changes: 11 additions & 31 deletions keep/api/bl/incidents_bl.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ def create_incident(
"Incident DTO created",
extra={"incident_id": new_incident_dto.id, "tenant_id": self.tenant_id},
)
self.__update_client_on_incident_change()
self.update_client_on_incident_change()
self.logger.info(
"Client updated on incident change",
extra={"incident_id": new_incident_dto.id, "tenant_id": self.tenant_id},
)
self.__run_workflows(new_incident_dto, "created")
self.send_workflow_event(new_incident_dto, "created")
self.logger.info(
"Workflows run on incident",
extra={"incident_id": new_incident_dto.id, "tenant_id": self.tenant_id},
Expand Down Expand Up @@ -113,13 +113,13 @@ async def add_alerts_to_incident(
"Alerts pushed to elastic",
extra={"incident_id": incident_id, "alert_fingerprints": alert_fingerprints},
)
self.__update_client_on_incident_change(incident_id)
self.update_client_on_incident_change(incident_id)
self.logger.info(
"Client updated on incident change",
extra={"incident_id": incident_id, "alert_fingerprints": alert_fingerprints},
)
incident_dto = IncidentDto.from_db_incident(incident)
self.__run_workflows(incident_dto, "updated")
self.send_workflow_event(incident_dto, "updated")
self.logger.info(
"Workflows run on incident",
extra={"incident_id": incident_id, "alert_fingerprints": alert_fingerprints},
Expand All @@ -146,7 +146,7 @@ def __update_elastic(self, incident_id: UUID, alert_fingerprints: List[str]):
except Exception:
self.logger.exception("Failed to push alert to elasticsearch")

def __update_client_on_incident_change(self, incident_id: Optional[UUID] = None):
def update_client_on_incident_change(self, incident_id: Optional[UUID] = None):
if self.pusher_client is not None:
self.logger.info(
"Pushing incident change to client",
Expand All @@ -162,7 +162,7 @@ def __update_client_on_incident_change(self, incident_id: Optional[UUID] = None)
extra={"incident_id": incident_id, "tenant_id": self.tenant_id},
)

def __run_workflows(self, incident_dto: IncidentDto, action: str):
def send_workflow_event(self, incident_dto: IncidentDto, action: str) -> None:
try:
workflow_manager = WorkflowManager.get_instance()
workflow_manager.insert_incident(self.tenant_id, incident_dto, action)
Expand Down Expand Up @@ -238,17 +238,8 @@ def delete_incident(self, incident_id: UUID) -> None:
)
if not deleted:
raise HTTPException(status_code=404, detail="Incident not found")
self.__update_client_on_incident_change()
try:
workflow_manager = WorkflowManager.get_instance()
self.logger.info("Adding incident to the workflow manager queue")
workflow_manager.insert_incident(self.tenant_id, incident_dto, "deleted")
self.logger.info("Added incident to the workflow manager queue")
except Exception:
self.logger.exception(
"Failed to run workflows based on incident",
extra={"incident_id": incident_dto.id, "tenant_id": self.tenant_id},
)
self.update_client_on_incident_change()
self.send_workflow_event(incident_dto, "deleted")

def update_incident(
self,
Expand All @@ -269,17 +260,6 @@ def update_incident(
if not incident:
raise HTTPException(status_code=404, detail="Incident not found")

new_incident_dto = IncidentDto.from_db_incident(incident)
try:
workflow_manager = WorkflowManager.get_instance()
self.logger.info("Adding incident to the workflow manager queue")
workflow_manager.insert_incident(
self.tenant_id, new_incident_dto, "updated"
)
self.logger.info("Added incident to the workflow manager queue")
except Exception:
self.logger.exception(
"Failed to run workflows based on incident",
extra={"incident_id": new_incident_dto.id, "tenant_id": self.tenant_id},
)
return new_incident_dto
incident_dto = IncidentDto.from_db_incident(incident)
self.send_workflow_event(incident_dto, "updated")
return incident_dto
Loading
Loading