I wanted to provide over a query I recently started to use to determine how long an alert has been active. This was built to be used as a widget for the modern dashboard, but could easily be modified to work as a custom query on the classic dashboard or a report. If anyone sees anything off on the logic please let me know.
I forgot who published the original query, but I ended up taking their logic for the time conversions for Minutes/Days/etc... I also saw some queries where RelatedNodeCaption was '[Self]' if it was a node object, which I liked so I included that as well. Once again, I forget who the original author of that one was.
The query pulls up the list of Reset action events from Alert History, then based on a match of the AlertActiveID, then looks up the time for the Trigger event.
I also included a variant that can be included to add custom properties of the object type. You will just need to update the Values in the subquery.
If anyone sees any holes in my logic, or has thoughts on improvement, please let me know.
Select [AH].AlertObjects.AlertConfigurations.Name
, '/Orion/NetPerfMon/ActiveAlertDetails.aspx?NetObject=AAT:' + ToString([AH].AlertObjectID) As AlertDetailURL
, [AH].AlertObjects.EntityCaption
, [AH].AlertObjects.EntityDetailsUrl
, Case [AH].AlertObjects.EntityType
When 'Orion.Nodes' then '[Self]'
Else [AH].AlertObjects.RelatedNodeCaption
End As RelatedNodeCaption
, [AH].AlertObjects.RelatedNodeDetailsUrl
-- , [CP].CUSTOMPROPERTYHERE
, ToLocal([TH].TimeStamp) as TriggerTime
, ToLocal([AH].TimeStamp) as ResetTime
, Case
When ([TH].TimeStamp is Null) then 'N/A'
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 10080
Then (ToSTring(Round(MINUTEDIFF([TH].TimeStamp,[AH].TimeStamp)/10080.0,1)) + ' Weeks')
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 1440
Then (ToSTring(Round(MINUTEDIFF([TH].TimeStamp,[AH].TimeStamp)/1440.0,1)) + ' Days')
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 60
Then (ToSTring(Round(MINUTEDIFF([TH].TimeStamp,[AH].TimeStamp)/60.0,1)) + ' Hours')
Else (ToString(MinuteDiff([TH].TimeStamp,[AH].TimeStamp)) + ' Minutes')
End as TimeActive
, Case
When ([TH].TimeStamp is Null) then '99999999'
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 10080
Then Round(MINUTEDIFF([TH].TimeStamp,[AH].TimeStamp)/10080.0,1)
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 1440
Then Round(MINUTEDIFF([TH].TimeStamp,[AH].TimeStamp)/1440.0,1)
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 60
Then Round(MINUTEDIFF([TH].TimeStamp,[AH].TimeStamp)/60.0,1)
Else MinuteDiff([TH].TimeStamp,[AH].TimeStamp)
End as TimeActiveValue
, Case
When ([TH].TimeStamp is Null) then 'N/A'
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 10080
Then 'Weeks'
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 1440
Then 'Days'
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 60
Then 'Hours'
Else 'Minutes'
End as TimeActiveUnit
From Orion.AlertHistory [AH]
Left Outer Join (
SELECT [H].AlertHistoryID
, [H].AlertActiveID
, [H].AlertObjectID
, [H].TimeStamp
From Orion.AlertHistory [H]
Where [H].EventType = 0
) as [TH] on [AH].AlertActiveID = [TH].AlertActiveID
Left Outer Join ( --Update results based on custom properties and value
Select [AO].AlertObjectID
, [AO].EntityCaption
, Case [AO].EntityType
When 'Orion.Nodes' Then 'Node'
When 'Orion.Volumes' then 'Volumes'
When 'Orion.APM.Application' then 'SAM - Application'
When 'Orion.APM.Component' then 'SAM - Component'
When 'Orion.Vim.VirtualMachines' then 'Virtualization - Virtual Machine'
When 'Orion.VIM.Datastores' then 'Virtualization - Datastores'
When 'Orion.SEUM.Transactions' then 'WPM - Transaction'
When 'Orion.SEUM.TransactionSteps' then 'WPM - Transaction Step'
When 'Orion.Engines' then 'SolarWinds Polling Engine'
When 'Orion.Groups' then 'SolarWinds Group'
Else Concat('N/A - ',[AO].EntityType)
End As AlertObjectType
-- , Case [AO].EntityType
-- When 'Orion.Nodes' Then [AO].Node.CustomProperties.VALUEHERE
-- When 'Orion.Volumes' then [V].CustomProperties.VALUEHERE
-- When 'Orion.APM.Application' then [App].CustomProperties.VALUEHERE
-- When 'Orion.APM.Component' then [C].Application.CustomProperties.VALUEHERE
-- When 'Orion.Vim.VirtualMachines' then [VM].Node.CustomProperties.VALUEHERE
-- When 'Orion.VIM.Datastores' then [DS].CustomProperties.VALUEHERE
-- When 'Orion.SEUM.Transactions' then [T].CustomProperties.VALUEHERE
-- When 'Orion.SEUM.TransactionSteps' then [TS].Transaction.CustomProperties.ValueHere
-- When 'Orion.Engines' then [SW].CustomProperties.VALUEHERE
-- When 'Orion.Groups' then [G].CustomProperties.VALUEHERE
-- Else Concat('N/A - ',[AO].EntityType)
-- End As VALUENAMEHERE
From Orion.AlertObjects [AO]
--Node can be linked from [AO].Node
Left Outer Join Orion.Volumes [V] on [AO].EntityDetailsUrl = [V].DetailsUrl --Volume
Left Outer Join Orion.APM.Application [App] on [AO].EntityDetailsUrl = [App].DetailsUrl --Application
Left Outer Join Orion.APM.Component [C] on [AO].EntityDetailsUrl = [C].DetailsUrl --Component
Left Outer Join Orion.VIM.VirtualMachines [VM] on [AO].EntityDetailsUrl = [VM].DetailsUrl --Virtual Machines
Left Outer Join Orion.VIM.DataStores [DS] on [AO].EntityDetailsURL = [DS].DetailsUrl --DataStores
Left Outer Join Orion.SEUM.Transactions [T] on [AO].EntityDetailsUrl = [T].DetailsUrl --WPM/Transaction
Left Outer Join Orion.SEUM.TransactionSteps [TS] on [AO].EntityDetailsUrl = [TS].DetailsUrl --WPM Step/Transaction Step
Left Outer Join Orion.SEUM.Agents [Agent] on [AO].EntityDetailsUrl = [Agent].DetailsUrl --WPM Player Servers/Agents
Left Outer Join Orion.Nodes [SW] on [AO].EntityCaption = [SW].Caption --SolarWinds/Orion Engine
Left Outer Join Orion.Groups [G] on [AO].EntityDetailsUrl = [G].DetailsUrl --Orion Groups
) as [CP] on [AH].AlertObjectID = [CP].AlertObjectID
Where [AH].EventType = 1
Select [AH].AlertObjects.AlertConfigurations.Name
, '/Orion/NetPerfMon/ActiveAlertDetails.aspx?NetObject=AAT:' + ToString([AH].AlertObjectID) As AlertDetailURL
, [AH].AlertObjects.EntityCaption
, [AH].AlertObjects.EntityDetailsUrl
, Case [AH].AlertObjects.EntityType
When 'Orion.Nodes' then '[Self]'
Else [AH].AlertObjects.RelatedNodeCaption
End As RelatedNodeCaption
, [AH].AlertObjects.RelatedNodeDetailsUrl
, ToLocal([TH].TimeStamp) as TriggerTime
, ToLocal([AH].TimeStamp) as ResetTime
, Case
When ([TH].TimeStamp is Null) then 'N/A'
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 10080
Then (ToSTring(Round(MINUTEDIFF([TH].TimeStamp,[AH].TimeStamp)/10080.0,1)) + ' Weeks')
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 1440
Then (ToSTring(Round(MINUTEDIFF([TH].TimeStamp,[AH].TimeStamp)/1440.0,1)) + ' Days')
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 60
Then (ToSTring(Round(MINUTEDIFF([TH].TimeStamp,[AH].TimeStamp)/60.0,1)) + ' Hours')
Else (ToString(MinuteDiff([TH].TimeStamp,[AH].TimeStamp)) + ' Minutes')
End as TimeActive
, Case
When ([TH].TimeStamp is Null) then '99999999'
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 10080
Then Round(MINUTEDIFF([TH].TimeStamp,[AH].TimeStamp)/10080.0,1)
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 1440
Then Round(MINUTEDIFF([TH].TimeStamp,[AH].TimeStamp)/1440.0,1)
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 60
Then Round(MINUTEDIFF([TH].TimeStamp,[AH].TimeStamp)/60.0,1)
Else MinuteDiff([TH].TimeStamp,[AH].TimeStamp)
End as TimeActiveValue
, Case
When ([TH].TimeStamp is Null) then 'N/A'
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 10080
Then 'Weeks'
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 1440
Then 'Days'
When MinuteDiff([TH].TimeStamp,[AH].TimeStamp) > 60
Then 'Hours'
Else 'Minutes'
End as TimeActiveUnit
From Orion.AlertHistory [AH]
Left Outer Join (
SELECT [H].AlertHistoryID
, [H].AlertActiveID
, [H].AlertObjectID
, [H].TimeStamp
From Orion.AlertHistory [H]
Where [H].EventType = 0
) as [TH] on [AH].AlertActiveID = [TH].AlertActiveID
Where [AH].EventType = 1