SCOM Dashboard — unhealthy objects with missing monitor alert

Привет.

Всем администраторам Operations Manager известно, что пользователи системы мониторинга иногда закрывают алерты, которые создаются мониторами. Одно из решений это проблемы — автоматический Reset этого монитора, используя тот же Orchestrator (детали тут). Не хотите поднимать ради этой задачи Orchestrator — используйте аналогичный скрипт и Scheduled Task. Но все это работает с алертами только после того, как вы внедрили одно из этих решений. Как же быть с уже закрытыми алертами? Или если вы приехали к клиенту впервые, как понять что он уже закрыл вручную, например, 90 дней назад?

Еще одна ситуация, которая может возникать, — это мониторы, которые не создают алертов или закрытие алертов вследствие превышения срока:

pic01

С этим вопросом я столкнулся достаточно давно. И тогда единственным решением определить unit monitor-ы с закрытыми алертами был sql-запрос к OperationsManager DB. Можно было сделать отчет и потом вручную искать каждый объект и ресетить монитор, или сделать это скриптом. В любом случае решение было корявым. В Operations Manager c выходом UR2 появился Powershell Grid Widget и решение перешло на новый качественный уровень.

Начнем с sql-запроса.

Получаем все объекты, у которых есть unit monitor в состоянии ERROR или WARN.

select
UnhealthyState.BaseManagedEntityId, -- object\instance id
UnhealthyState.MonitorName -- Monitor Name
from
dbo.StateView as UnhealthyState WITH (NOLOCK) 
where
UnhealthyState.HealthState in (3,2) --only ERROR и WARN
and UnhealthyState.OperationalState is not NULL --not aggregate or dependency monitor
and UnhealthyState.MonitorName not in
('Insert MonitorName' -- you can remove some motinor from query
,'Insert MonitorName'
)
--and UnhealthyState.MonitorName not like '%SQL%' -- you can use like or not like to show specific monitors
--and UnhealthyState.MonitorName not like '%network%'

Для удобства уважаемых читателей приведены варианты фильтров, которые позволят вам исключить определенные мониторы из выборки или, используя like\not like, выбирать мониторы с определенными ключевыми словами. (Это для неопытных в sql-запросах, опытные могут творить, что хотят 🙂 ).

Теперь нам нужно получить все открытые (Resolution State не 255) алерты и связать их с имеющимся запросом.

select
UnhealthyState.BaseManagedEntityId,
UnhealthyState.MonitorName,
OpenAlerts.Id
from
dbo.StateView as UnhealthyState WITH (NOLOCK)

left join dbo.AlertView as OpenAlerts
on
UnhealthyState.BaseManagedEntityId = OpenAlerts.MonitoringObjectId and
OpenAlerts.ResolutionState <> 255 and OpenAlerts.IsMonitorAlert = 1 and LanguageCode = 'ENU'

where
UnhealthyState.HealthState in (3,2) --only ERROR и WARN
and UnhealthyState.OperationalState is not NULL --not aggregate or dependency monitor
and UnhealthyState.MonitorName not in
('Insert MonitorName' -- you can remove some motinor from query
,'Insert MonitorName'
)
--and UnhealthyState.MonitorName not like '%SQL%' -- you can use like or not like to show specific monitors
--and UnhealthyState.MonitorName not like '%network%'
and
OpenAlerts.Id is NULL -- Alert was closed or did not exist

Последние штрихи — получаем полное имя объекта\инстанса и его класс.

select  --top 25 --Uncomment if your dashboard is working too long and get instances by parts
	PathT.FullName
	,ClassT.Name as ClassName
	,UnhealthyState.MonitorName
from
dbo.StateView as UnhealthyState WITH (NOLOCK) 

left join dbo.AlertView as OpenAlerts 
on  
UnhealthyState.BaseManagedEntityId = OpenAlerts.MonitoringObjectId and
OpenAlerts.ResolutionState <> 255 and OpenAlerts.IsMonitorAlert = 1 and LanguageCode = 'ENU'

inner join dbo.ManagedEntityGenericView PathT
 on PathT.id = UnhealthyState.BaseManagedEntityId and PathT.MonitoringClassId= UnhealthyState.TargetManagedEntityType  

inner join [dbo].[ManagedTypeView] As ClassT
 on ClassT.id = UnhealthyState.TargetManagedEntityType and ClassT.LanguageCode = 'ENU'

where
UnhealthyState.HealthState in (3,2) --only ERROR и WARN
and UnhealthyState.OperationalState is not NULL --not aggregate or dependency monitor
and UnhealthyState.MonitorName not in
('Insert MonitorName' -- you can remove some motinor from query
,'Insert MonitorName'
)
--and UnhealthyState.MonitorName not like '%SQL%' -- you can use like or not like to show specific monitors
--and UnhealthyState.MonitorName not like '%network%'
and
OpenAlerts.Id is NULL -- Alert was closed or did not exist

А теперь создадим Powershell Grid Widget Dashboard, где используем этот запрос для получения инстансов.
Для начала создайте Dashboard View -> Grid Layout и выберите 1 cell.

pic02

Добавляем widget.

pic03

В разделе Script

$SqlServer = "SQL Server FQDN"
$SqlCatalog = "OperationsManager"

$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SqlServer; Database = $SqlCatalog; Integrated Security = True"

$SQLQuery_Values = "
INSERT YOUR SQL QUERY HERE
"

$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SQLQuery_Values
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$SQLDataSet = New-Object System.Data.DataSet
[void]$SqlAdapter.Fill($SQLDataSet)
$classname_current = ""
$classname_pre = ""

if ($?) {
 $ScriptContext.Clear()
 if ($SQLDataSet.Tables[0].Rows.Count -gt 0) {
 foreach ($TableRow in $SQLDataSet.Tables[0].Rows){
 $classname_current = "$($TableRow.ClassName)"
 if($classname_current -ne $classname_pre )
 {
 $class = Get-SCOMClass -Name $TableRow.ClassName
 }
 $obj = Get-SCOMClassInstance -Class $class | ?{$_.Fullname -eq "$($TableRow.FullName)"}
 $dataObject = $ScriptContext.CreateFromObject($obj, "Id=Id,HealthState=HealthState,DisplayName=DisplayName,Path=Path", $null)
 $classname_pre = $classname_current

 $ScriptContext.ReturnCollection.Add($dataObject)
 }
 } 
}

Не забудьте вставить FQDN вашего sql сервера и ваш запроса (или для начала мой 🙂 ).
В результате вы должны получить отличный dashboard показывающий все инстансы в состоянии ERROR или WARN у которых нет открытых алетов (их или закрыли или небыло никогда).

Скачать Managment Pack  Unhealthy.objects.Dashboard. Не забудьте отредактировать dashboard и вставить FQDN вашего sql-сервера.

И еще, пользователь, который будет открывать этот Dashboard, должен иметь права read на базу OperationsManager. Так как нужна эта информация админам, тут проблем не должно возникнуть.

Буду рад комментариям и вопросам.

Александр Петлевой

Leave a Reply