Skip to content

Commit 897a7ec

Browse files
WIP Support trigger chains
1 parent 8d41417 commit 897a7ec

2 files changed

Lines changed: 63 additions & 12 deletions

File tree

library/Notifications/Model/IncidentHistory.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
* @property ?string $notification_state
4141
* @property ?DateTime $sent_at
4242
* @property ?string $event_id
43+
* @property ?int $triggered_by_id
4344
*
4445
* @property Query<Incident>|Incident $incident
4546
* @property Query<Contact>|Contact $contact
@@ -49,6 +50,7 @@
4950
* @property Query<RuleEscalation>|RuleEscalation $rule_escalation
5051
* @property Query<Channel>|Channel $channel
5152
* @property Query<NotificationHistory>|Collection<NotificationHistory> $notification_history
53+
* @property Query<IncidentHistory>|IncidentHistory $triggered_by
5254
*/
5355
class IncidentHistory extends Model
5456
{
@@ -81,7 +83,8 @@ public function getColumns(): array
8183
'message',
8284
'notification_state',
8385
'sent_at',
84-
'event_id'
86+
'event_id',
87+
'triggered_by_id'
8588
];
8689
}
8790

@@ -140,6 +143,9 @@ public function createRelations(Relations $relations): void
140143
$relations->belongsTo('rule_escalation', RuleEscalation::class)->setJoinType('LEFT');
141144
$relations->belongsTo('channel', Channel::class)->setJoinType('LEFT');
142145
$relations->hasMany('notification_history', NotificationHistory::class)->setJoinType('LEFT');
146+
$relations->belongsTo('triggered_by', self::class)
147+
->setCandidateKey('triggered_by_id')
148+
->setJoinType('LEFT');
143149
}
144150

145151
/**

library/Notifications/Widget/Detail/NotificationHistoryDetail.php

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
use Icinga\Module\Notifications\Common\IncidentHistoryType;
1212
use Icinga\Module\Notifications\Model\IncidentHistory;
1313
use Icinga\Module\Notifications\Model\NotificationHistory;
14+
use Icinga\Module\Notifications\Model\Rule;
15+
use Icinga\Module\Notifications\Model\RuleEscalation;
1416
use Icinga\Module\Notifications\View\IncidentRenderer;
1517
use Icinga\Module\Notifications\Widget\ItemList\ObjectList;
1618
use ipl\Html\Attributes;
@@ -120,16 +122,35 @@ protected function createIncident(): array
120122

121123
protected function createReason(): array
122124
{
125+
[$reason, $rule, $ruleEscalation] = $this->resolveTriggerChain();
123126
$triggerChain = new HtmlElement(
124127
'div',
125128
Attributes::create(['class' => 'trigger-chain']),
126129
new HtmlElement(
127130
'span',
128131
Attributes::create(['class' => 'item']),
129-
Text::create($this->resolveReason()->getLabel())
132+
Text::create($reason->getLabel())
130133
)
131134
);
132135

136+
if ($rule !== null) {
137+
$triggerChain->addHtml(
138+
new HtmlElement(
139+
'span',
140+
Attributes::create(['class' => 'item']),
141+
Text::create(sprintf($this->translate('Rule %s matched'), $rule->name))
142+
),
143+
new HtmlElement(
144+
'span',
145+
Attributes::create(['class' => 'item']),
146+
Text::create(sprintf(
147+
$this->translate('Escalation triggered (%s)'),
148+
EscalationConditionDescriber::describe($ruleEscalation?->condition)
149+
))
150+
)
151+
);
152+
}
153+
133154
$triggerChain->addHtml(
134155
new HtmlElement(
135156
'span',
@@ -193,17 +214,41 @@ protected function createReason(): array
193214
];
194215
}
195216

196-
protected function resolveReason(): IncidentHistoryType
217+
/**
218+
* Get the root cause and the matching rule and escalation that triggered the notification
219+
*
220+
* @return array{IncidentHistoryType, ?Rule, ?RuleEscalation}
221+
*/
222+
protected function resolveTriggerChain(): array
197223
{
198-
/** @var ?IncidentHistory $entry */
199-
$entry = IncidentHistory::on(Database::get())
200-
->filter(Filter::all(
201-
Filter::equal('incident_id', $this->notificationHistory->incident_id),
202-
Filter::equal('event_id', $this->notificationHistory->event_id)
203-
))
204-
->first();
205-
206-
return $entry?->type ?? $this->notificationHistory->incident_history->type;
224+
$reason = $this->notificationHistory->incident_history->type;
225+
$rule = null;
226+
$ruleEscalation = null;
227+
228+
$triggeredBy = $this->notificationHistory->incident_history->triggered_by_id;
229+
while ($triggeredBy !== null) {
230+
$node = IncidentHistory::on(Database::get())
231+
->with(['rule', 'rule_escalation'])
232+
->filter(Filter::equal('id', $triggeredBy))
233+
->first();
234+
235+
if ($node === null) {
236+
break;
237+
}
238+
239+
if ($node->rule_id !== null) {
240+
$rule = $node->rule;
241+
}
242+
243+
if ($node->rule_escalation_id !== null) {
244+
$ruleEscalation = $node->rule_escalation;
245+
}
246+
247+
$reason = $node->type;
248+
$triggeredBy = $node->triggered_by_id;
249+
}
250+
251+
return [$reason, $rule, $ruleEscalation];
207252
}
208253

209254
protected function assemble(): void

0 commit comments

Comments
 (0)