for those people who do not understand Russian please use the google translator
Представим, что у вас есть System Center Operations Manager, агент собирает метрики, что-то там мониторит, мучает WMI ваших систем и наступает тот момент, когда вы хотите собрать дашборд или быстро посмотреть метрики, и вот тут начинается веселье. У нас есть «чудесная» консоль, есть репорт сервер с SSRS, есть даже веб консоль, но всё это такое … ну, вы поняли, не очень быстрое, не очень красивое и прочее.
В мире красноглазых и не очень, я про DevOps если что, есть много интересных и бесплатных решений, и одно их них — это Grafana. С версии 5.0+ она поддерживает источник данных для Microsoft SQL, и тут я подумал, хм, у нас же есть 2 базы данных OperationsManager и OpsMgr Data Warehouse. А почему бы нам «не затолкать» в эту самую Grafana наши метрики. Очень удивило, что в интернете постов на эту тему почти нет. В посте на реддите все закончилось «I just started trying to find useful tables last week. Not much luck so far». Ну ок, будем разбираться.

Есть два способа: правильный и второй.
Способ правильный: берём Telegraf, InfluxDB и Grafana. Telegraf у нас отгружает метрики в базу InfluxDB, а Grafana рисует нам все. На самом деле есть еще более правильный способ. Вы отгружаете метрики в какую-нибудь PostgreSQL и там храните все данные 1-2-3 года или сколько вам надо, а вот для отрисовки в Grafana используете InfluxDB, т.к. она отлично подходит для хранения временных рядов.
Способ второй: у нас уже есть все метрики и все данные в нашей MS SQL базе, а Grafana умеет в t-sql запросы, пишем нужные нам селекты, а Grafana всё рисует. Вот про второй способ и поговорим.

Я не буду писать про то, как установить Grafana, вы можете её сразу запустить в dockere. Напомню только то, что ваша база от SCOMa должна работать в mixed режиме, т.к. из Grafana мы будем подключать через SQL учетку, без всяких Windows аутентификаций. Если у вас Grafana на винде, то забейте, все будет работать. Если у вас настроен krb5.conf, то молодцы. Короче, разберётесь, а то тут еще целый пост можно делать, как аутентифицироваться на «скуле». Ну и понятно, что вы должны нарезать права для чтения — db_datareader.
Grafana поставили, добавляем новый Data Source, заполняем все данные для нашего MS SQL сервера. Добавлю, что пока в этом посте мы будем работать с OperationsManager базой. Да, я знаю, что метрики там хранятся за 7 дней, ну или как у вас настроено в SCOM — Administration — Settings — Database Grooming. С DataWarehouse разберемся потом.
Создаём новый dashboard и сразу идём в его настройки (Settings в правом углу). Нам необходимо создать новую Variables. Идея в том, что в нашем дашборде будет выпадающее меню и в зависимости от выбора в этом меню будут меняться метрики на экране. Привяжемся к имени хостнейма, а точнее выгрузим все FQDN от агентов, которые есть в SCOM.
1 2 3 |
select bme.DisplayName from MT_HealthService mths INNER JOIN BaseManagedEntity bme on bme.BaseManagedEntityId = mths.BaseManagedEntityId |

Отлично, имена хостов у нас есть. Мы создадим несколько панелей: графики с производительностью, список текущих алёртов из консоли и отобразим суммарное здоровье самого агента SCOM.
Поехали.

Создаем новую панель Graph и нарисуем несколько графиков: % Processor Time, % Memory Used, Network Bytes Total/Sec и Disc Average sec/transfer. Можно получить и всё остальное, но как? Для этого надо получить ObjectName и CounterName. Для каждого агента SCOM эти данные будут разные, все зависит от ваших пакетов управлений. Берем имя любого хоста с агентом SCOM и селектим в базу.

1 2 3 4 5 6 7 8 9 |
select Distinct Path, ObjectName, CounterName, InstanceName from PerformanceDataAllView pdv with (NOLOCK) inner join PerformanceCounterView pcv on pdv.performancesourceinternalid = pcv.performancesourceinternalid inner join BaseManagedEntity bme on pcv.ManagedEntityId = bme.BaseManagedEntityId where path = 'hostname.domain.com' order by objectname, countername, InstanceName |

Например, контроллер домена. Видим, что кроме метрик производительности, у нас еще есть правила, которые собирают метрики от VMware, от пакета управления Active Directory и т.д.
Для отрисовки панели Graph необходимо передать 3 значения: время, значение и имя метрики. В нашем случае имя метрики будет имя хоста, значение — данные в базе и время. Прямой селект в базу будет такой:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
select TimeSampled, SampleValue as value, path as metric from PerformanceDataAllView pdv with (NOLOCK) inner join PerformanceCounterView pcv on pdv.performancesourceinternalid = pcv.performancesourceinternalid inner join BaseManagedEntity bme on pcv.ManagedEntityId = bme.BaseManagedEntityId where path in('hostname.domain.com') AND objectname = 'Processor Information' AND countername = '% Processor Time' group by path, TimeSampled, SampleValue order by timesampled desc |

Но для графаны его требуется немного подправить, чтобы как минимум работала кнопка для фильтра по времени и графана понимала, где какие значения. Для этого метрики времени оборачиваем макросом $__timeEpoch(data), добавляем в запрос работу с фильтром $__timeFilter(data) и подключаем нашу переменную $hostname — path in($hostname). Последнее будет передавать в запрос все хостнеймы, которые мы выберем в выпадающем меню нашего дашборда.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
select $__timeEpoch(TimeSampled), SampleValue as value, path as metric from PerformanceDataAllView pdv with (NOLOCK) inner join PerformanceCounterView pcv on pdv.performancesourceinternalid = pcv.performancesourceinternalid inner join BaseManagedEntity bme on pcv.ManagedEntityId = bme.BaseManagedEntityId where path in($hostname) AND objectname = 'Processor Information' AND countername = '% Processor Time' and $__timeFilter(TimeSampled) group by path, TimeSampled, SampleValue order by timesampled ASC |
Выбираем наш datasource и копи-пастим t-sql запрос.

Создаем еще 3 панели для % Memory Used, Network Bytes Total/Sec и Disc Average sec/transfer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
select $__timeEpoch(TimeSampled), SampleValue as value, path as metric from PerformanceDataAllView pdv with (NOLOCK) inner join PerformanceCounterView pcv on pdv.performancesourceinternalid = pcv.performancesourceinternalid inner join BaseManagedEntity bme on pcv.ManagedEntityId = bme.BaseManagedEntityId where path in($hostname) AND objectname = 'Memory' AND countername = 'PercentMemoryUsed' and $__timeFilter(TimeSampled) group by path, TimeSampled, SampleValue order by timesampled ASC |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
select $__timeEpoch(TimeSampled), SampleValue as value, path as metric from PerformanceDataAllView pdv with (NOLOCK) inner join PerformanceCounterView pcv on pdv.performancesourceinternalid = pcv.performancesourceinternalid inner join BaseManagedEntity bme on pcv.ManagedEntityId = bme.BaseManagedEntityId where path in($hostname) AND (objectname = 'Network Adapter' or objectname = 'Network Interface') AND countername = 'Bytes Total/sec' and $__timeFilter(TimeSampled) group by path, TimeSampled, SampleValue order by timesampled ASC |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
select $__timeEpoch(TimeSampled), SampleValue as value, path + ' ' + InstanceName as metric from PerformanceDataAllView pdv with (NOLOCK) inner join PerformanceCounterView pcv on pdv.performancesourceinternalid = pcv.performancesourceinternalid inner join BaseManagedEntity bme on pcv.ManagedEntityId = bme.BaseManagedEntityId where path in($hostname) AND objectname = 'LogicalDisk' AND countername = 'Avg. Disk sec/Transfer' and $__timeFilter(TimeSampled) group by path, TimeSampled, SampleValue, InstanceName order by timesampled ASC |
Если вы всё сделали правильно, то должно быть что-то такое. При выборе хостов в выпадающем меню, они будут добавляться на графики.

Теперь мы можем добавить представление Alerts из консоли Operation Manager. Создадим панель Table и добавим запрос.
! обратите внимание ! Ниже sql запрос, в блоке кода никак не хочет ставить знак < — в двух местах AND av.ResolutionState < 255
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
WITH ALERT_SELECTION ( LastModified, AlertStringName, Severity, Alert_ResolutionState, MonitoringObjectDisplayName,ManagementPack) AS ( SELECT av.LastModified, av.AlertStringName, av.Severity, Alert_ResolutionState = CASE WHEN av.ResolutionState = '255' THEN 'Closed' WHEN AV.ResolutionState = '254' THEN 'Resolved' WHEN AV.ResolutionState = '251' THEN 'Blackout' WHEN AV.ResolutionState = '250' THEN 'Scheduled' WHEN AV.ResolutionState = '249' THEN 'Acknowledge' WHEN AV.ResolutionState = '248' THEN 'Assigned to Engineering' WHEN AV.ResolutionState = '247' THEN 'Awaiting Evidence' WHEN AV.ResolutionState = '3' THEN 'Notified' WHEN AV.ResolutionState = '0' THEN 'New' END, MonitoringObjectDisplayName, mp.MPName AS ManagementPack FROM OperationsManager.dbo.AlertView (NOLOCK) av LEFT JOIN OperationsManager.dbo.RuleView (NOLOCK) Rv ON av.MonitoringRuleId = rv.Id JOIN OperationsManager.dbo.ManagementPack mp ON rv.ManagementPackId = mp.ManagementPackId AND av.ResolutionState < 255 UNION SELECT av.LastModified, av.AlertStringName, av.Severity, Alert_ResolutionState = CASE WHEN av.ResolutionState = '255' THEN 'Closed' WHEN AV.ResolutionState = '254' THEN 'Resolved' WHEN AV.ResolutionState = '251' THEN 'Blackout' WHEN AV.ResolutionState = '250' THEN 'Scheduled' WHEN AV.ResolutionState = '249' THEN 'Acknowledge' WHEN AV.ResolutionState = '248' THEN 'Assigned to Engineering' WHEN AV.ResolutionState = '247' THEN 'Awaiting Evidence' WHEN AV.ResolutionState = '3' THEN 'Notified' WHEN AV.ResolutionState = '0' THEN 'New' END, MonitoringObjectDisplayName, mp.MPName AS ManagementPack FROM OperationsManager.dbo.AlertView (NOLOCK) av JOIN OperationsManager.dbo.MonitorView (NOLOCK) Mv ON av.MonitoringRuleId = Mv.Id JOIN OperationsManager.dbo.ManagementPack mp ON mv.ManagementPackId = mp.ManagementPackId AND av.ResolutionState < 255 ) SELECT CONVERT(varchar, DATEADD(hour, 3 , LastModified), 120) as Time, AlertStringName, Severity, MonitoringObjectDisplayName, ManagementPack FROM ALERT_SELECTION Where $__timeFilter(LastModified) GROUP by LastModified, AlertStringName, Severity, MonitoringObjectDisplayName, ManagementPack ORDER BY LastModified ASC |

Так мы получили все Critical и Warning, которые вы видите каждый день в консоле. Для того, чтобы разукрасить табличку, то на вкладке Column Styles требуется немного поиграть с настройками. Severity возвращает целые значения — 0, 1 и 2.

Теперь можно добавить статусы агентов для класса Windows.Computer. Есть несколько вариантов. Мы можем создать таблицу и выводить статус, либо можем создать панель Singlestat и в зависимости от количества выбранных хостов, панели будут сами отрисовываться в дашборде.
Для таблицы создаём Table, добавляем запрос, меняем в Column Style настройки.
1 2 3 4 5 6 7 8 9 10 11 |
SELECT s.HealthState as 'Health', LEFT(bme.DisplayName, CHARINDEX('.', bme.DisplayName) - 1) as 'Name' FROM State s JOIN BaseManagedEntity bme ON s.BaseManagedEntityId = bme.BaseManagedEntityId JOIN MonitorView mv ON mv.Id = s.MonitorId WHERE bme.DisplayName in($hostname) and mv.Name = 'System.Health.EntityState' AND FullName like 'Microsoft.Windows.Computer:%' |


Для Singlestat
1 2 3 4 5 6 7 8 9 10 |
SELECT s.HealthState as 'Health', LEFT(bme.DisplayName, CHARINDEX('.', bme.DisplayName) - 1) as 'Name' FROM State s JOIN BaseManagedEntity bme ON s.BaseManagedEntityId = bme.BaseManagedEntityId JOIN MonitorView mv ON mv.Id = s.MonitorId WHERE bme.DisplayName in($hostname) and mv.Name = 'System.Health.EntityState' AND FullName like 'Microsoft.Windows.Computer:%' |

Для Singlestat на вкладке потребуется добавить значение hostname в For each value of, тогда при выборе эта панель будет «размножаться», как на скрине выше.

И совсем немного разукрасить в Options.

И вот наш финальный дашборд. Временные интервалы в правом углу и выпадающее меню работают, авторефреш — ок. Энджой.
В будущем разберемся, как сделать дриллдаун по панели и уже провалиться внутрь требуемого сервиса/сервера/тэга.

Тоха, отличная и самое главное полезная статья!
Супер статья! Спасибо!
Твою статью даже Microsoft использует в рамках премьер саппорта
[…] System Center Operations Manager и Grafana: рисуем графики […]
Спасибо большое за статью!
Не могу понять, почему то у меня на 19м SCOMe графана ужасно рисует графики. Вроде делаю все как в статье, но когда меняю время (Last 5-10-15..min), данные прыгают по какой то непонятной схеме
А если в селекте несколько различных значений, например несколько сетевых интерфейсов, как их разбить на несколько граф?