Всем привет. В этой статье я расскажу, как контролировать работу windows-службы с помощью системы мониторинга Zidium.
Сначала о том, что такое мониторинг и зачем вообще он нужен. Был у меня заказ на приложение, которое должно собирать данные с нескольких систем, выполнять аналитику, и отправлять данные в систему отчётов. Приложение я реализовал в виде windows-службы, развернул на хостинге. Заказчик передал дальнейшее сопровождение службы мне на аутсорс, то есть я отвечаю за её работоспособность и за исправление ошибок.
Но возник вопрос — как мне отслеживать возможные проблемы со службой?
Что, если служба остановится из-за внутренней ошибки или зависнет? Я об этом не узнаю, пока заказчик не предъявит мне претензию, что данные несколько дней не обновлялись. Кроме того, мне нужны данные о случающихся ошибках, логи для анализа и т.п.
Какую информацию о состоянии службы я хочу иметь:
Вот тут на помощь и приходят системы мониторинга. Для этого проекта я выбрал мониторинг Zidium. Это облачная система мониторинга, которую можно использовать совершенно бесплатно неограниченное время. У него есть всё, что мне нужно, в одном флаконе.
Посмотрим сначала на исходный код службы, без мониторинга. Служба написана на C# в среде VS 2015.
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/300/992/7c7/3009927c7aa69b23889b35a00a753256.png)
Тут всё стандартно для windows — поток, бесконечный цикл с прерыванием работы, некоторая задержка в конце итерации.
Цикл выполняет методы, которые собирают, обрабатывают и отправляют данные. Что конкретно они делают, для этой статьи неважно.
Подключим Zidium к проекту. Это делается с помощью Nuget-пакета. Он добавляет dll и файл zidium.xml с настройками. В xml-файле я задал параметры доступа к аккаунту. Можно не использовать файл, а задавать всё программно, но мне показалось, что такой конфиг — это более правильно.
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/688/620/06b/68862006b49ee476360f2a590f8163ac.png)
Все примеры использования я брал из документации на сайте Zidium.
Сначала создадим вспомогательный класс, который будет соединяться с системой и получать “компонент”. В моём случае компонент — это сама служба и есть. Здесь всё как рекомендуется в документации, поправил только названия.
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/a6c/c59/3fe/a6cc593fe641259963f0bf3cba0cb919.png)
Чтобы проверить создание компонента, я вставил получение компонента в метод запуска сервиса и вызывал у него метод IsFake (дело в том, что компонент на стороне Zidium создаётся только когда с ним будет выполнена какая-то реальная работа). Для обычной работы это не нужно, после теста этот вызов можно удалить.
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/4d3/094/1dd/4d30941dd2c1b48832c11d5bbf51caf5.png)
После запуска в личном кабинете появился компонент.
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/a6f/874/bbe/a6f874bbef8e6ab14486419eab8f7d53.png)
Цвет у него серый, потому что никаких данных мы пока не передавали.
Добавим теперь сигнал активности. Для этого используются так называемые “проверки” (“unittests”).
В самом начале нужно создать для “компонента” саму проверку и запомнить её в переменной.
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/91a/952/a90/91a952a909fe9f586052d9ddb4bf7ab4.png)
Теперь в каждой итерации рабочего цикла отправляем результат проверки, что служба работает как надо. При этом я указываю время актуальности. Это именно то время, через которое система поднимет тревогу, если очередной сигнал не поступит.
У меня данные собираются раз в час, поэтому я указал актуальность 2 часа — запас на 1 цикл работы. По хорошему, конечно, надо учитывать реальное время работы методов, но я решил не усложнять.
Запускаем службу, и в личном кабинете видим зелёный компонент и зелёную проверку. Всё хорошо.
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/8ac/dab/2f3/8acdab2f38a39a13c3439c2de1621ddb.png)
Для теста я указал время актуальности 1 минуту (чтобы долго не ждать) и остановил службу.
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/301/f5b/85b/301f5b85bbedcbdbe607facd443a4b86.png)
Через минуту компонент с проверкой стали красными, и мне на почту пришло письмо с уведомлением об отсутствии сигнала.
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/9c2/b90/1ac/9c2b901ac0b44c7b640e6b1bc5b3eb5c.png)
Все уведомления довольно гибко настраиваются, и можно получать их на email и по sms. У каждого пользователя свои контакты и свои настройки уведомлений. Отлично, эта задача решена.
Теперь разберёмся с ошибками. Здесь всё проще.
try {} и в catch отправляем ошибку. Есть удобный готовый метод, который из Exception выделяет сообщение, стек и т.п. и формирует ошибку.
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/b93/6d4/b11/b936d4b11eabe08eaa16bad4af45248b.png)
Для теста я просто вызвал throw new Exception() в теле цикла. Вот как выглядит ошибка в личном кабинете:
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/a1b/623/e69/a1b623e691f1aa86a7a4d81972c2353b.png)
Опять же, я получаю о ней уведомление, если мне это надо.
Надо сказать, что Zidium довольно интеллектуально понимает, что несколько ошибок являются на самом деле одной и той же. Такие ошибки соединяются в одну, что очень удобно. И спама из уведомлений тоже не будет.
Далее у нас лог. Работа с логом сделана аналогично другим библиотекам логирования, таким как nLog или Log4Net. Просто пишем что хотим, указывая уровень (важность) записи.
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/a07/eee/20d/a07eee20d12b8acc40224acf7b5420e0.png)
Бонус — к каждой записи лога можно прикрепить любое количество допсвойств, в которые можно поместить что угодно — например, xml. Они не замусоривают сам лог, но их всегда можно посмотреть.
Вот так выглядит лог в личном кабинете:
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/210/3a4/55d/2103a455dab85116bc695849802845ab.png)
Для меня это гораздо удобнее, чем читать огромные тестовые файлы.
Помимо облачного лога, Zidium на всякий случай пишет и классический файловый лог (хотя это можно отключить). Приятно, что не надо подключать ещё и другие библиотеки логирования. Всё же файловый лог может оказать полезным в крайних случаях, например, если не было связи с облаком.
Наконец, статистика по производительности. Для этого используются “метрики”. Я замеряю общее время работы интересующих меня методов.
У метрики есть название и значение, и отправляется она так:
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/e08/592/b22/e08592b222536773969e408f49c2a53f.png)
В личном кабинете можно посмотреть детально всю историю метрики.
Сразу же считаются основные агрегаты за выбранный период — максимум, минимум и среднее.
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/67c/54b/2ca/67c54b2ca0ea0ffe46124992e905e660.png)
Жаль, нельзя скачать данные в формате xlsx или csv, это могло бы пригодиться для собственного анализа.
Ещё для метрик можно настраивать правила предупреждений о выходе значения за выбранный диапазон. Тогда о метриках тоже будут приходить уведомления. Но я это не использовал, мне полезно просто иметь статистику времени работы.
Моя служба посылает в мониторинг сигнал активности, собирает ошибки, пишет облачный лог и ведёт статистику производительности.
Я получу уведомление, если служба вдруг остановится или зависнет. Я получу уведомление, если возникнет любая ошибка.
Теперь я спокоен за сделанную мной работу и за выполнение обязательств перед заказчиком )
Зачем мониторинг?
Сначала о том, что такое мониторинг и зачем вообще он нужен. Был у меня заказ на приложение, которое должно собирать данные с нескольких систем, выполнять аналитику, и отправлять данные в систему отчётов. Приложение я реализовал в виде windows-службы, развернул на хостинге. Заказчик передал дальнейшее сопровождение службы мне на аутсорс, то есть я отвечаю за её работоспособность и за исправление ошибок.
Но возник вопрос — как мне отслеживать возможные проблемы со службой?
Что, если служба остановится из-за внутренней ошибки или зависнет? Я об этом не узнаю, пока заказчик не предъявит мне претензию, что данные несколько дней не обновлялись. Кроме того, мне нужны данные о случающихся ошибках, логи для анализа и т.п.
Какую информацию о состоянии службы я хочу иметь:
- Отслеживание сигнала активности (так называемое “биение сердца”, heartbeat). Если служба остановится, сигнал перестанет поступать и станет понятно — что-то не так.
- Сбор подробной информации об ошибках. Мне же их исправлять. Так что нужно как можно больше данных — время, сообщение, стек и т.п.
- Ведение лога в облаке. Почему не файл? Служба работает на боевом сервере, туда доступ только у админа. Админ человек занятой, логи ему некогда искать и присылать мне. Или оказывается, что логи слишком большие и не отправляются через корпоративную почту. В общем, сложно всё с файлом.
- Уведомления о проблемах по email и, хорошо бы, по sms. Мне — об ошибках, админу — об остановке службы.
- Некоторая статистика по производительности — замер времени выполнения ключевых участков обработки данных. Это мне пригодится для оптимизаций.
- Ну и крайне желательно всё это иметь в одном месте, а не в разных системах учёта.
Вот тут на помощь и приходят системы мониторинга. Для этого проекта я выбрал мониторинг Zidium. Это облачная система мониторинга, которую можно использовать совершенно бесплатно неограниченное время. У него есть всё, что мне нужно, в одном флаконе.
Как это работает
Посмотрим сначала на исходный код службы, без мониторинга. Служба написана на C# в среде VS 2015.
![image](https://habrastorage.org/getpro/habr/post_images/300/992/7c7/3009927c7aa69b23889b35a00a753256.png)
Тут всё стандартно для windows — поток, бесконечный цикл с прерыванием работы, некоторая задержка в конце итерации.
Цикл выполняет методы, которые собирают, обрабатывают и отправляют данные. Что конкретно они делают, для этой статьи неважно.
Подключим Zidium к проекту. Это делается с помощью Nuget-пакета. Он добавляет dll и файл zidium.xml с настройками. В xml-файле я задал параметры доступа к аккаунту. Можно не использовать файл, а задавать всё программно, но мне показалось, что такой конфиг — это более правильно.
![image](https://habrastorage.org/getpro/habr/post_images/688/620/06b/68862006b49ee476360f2a590f8163ac.png)
Все примеры использования я брал из документации на сайте Zidium.
Сначала создадим вспомогательный класс, который будет соединяться с системой и получать “компонент”. В моём случае компонент — это сама служба и есть. Здесь всё как рекомендуется в документации, поправил только названия.
![image](https://habrastorage.org/getpro/habr/post_images/a6c/c59/3fe/a6cc593fe641259963f0bf3cba0cb919.png)
Чтобы проверить создание компонента, я вставил получение компонента в метод запуска сервиса и вызывал у него метод IsFake (дело в том, что компонент на стороне Zidium создаётся только когда с ним будет выполнена какая-то реальная работа). Для обычной работы это не нужно, после теста этот вызов можно удалить.
![image](https://habrastorage.org/getpro/habr/post_images/4d3/094/1dd/4d30941dd2c1b48832c11d5bbf51caf5.png)
После запуска в личном кабинете появился компонент.
![image](https://habrastorage.org/getpro/habr/post_images/a6f/874/bbe/a6f874bbef8e6ab14486419eab8f7d53.png)
Цвет у него серый, потому что никаких данных мы пока не передавали.
Сигнал активности (HeartBeat)
Добавим теперь сигнал активности. Для этого используются так называемые “проверки” (“unittests”).
В самом начале нужно создать для “компонента” саму проверку и запомнить её в переменной.
![image](https://habrastorage.org/getpro/habr/post_images/91a/952/a90/91a952a909fe9f586052d9ddb4bf7ab4.png)
Теперь в каждой итерации рабочего цикла отправляем результат проверки, что служба работает как надо. При этом я указываю время актуальности. Это именно то время, через которое система поднимет тревогу, если очередной сигнал не поступит.
У меня данные собираются раз в час, поэтому я указал актуальность 2 часа — запас на 1 цикл работы. По хорошему, конечно, надо учитывать реальное время работы методов, но я решил не усложнять.
Запускаем службу, и в личном кабинете видим зелёный компонент и зелёную проверку. Всё хорошо.
![image](https://habrastorage.org/getpro/habr/post_images/8ac/dab/2f3/8acdab2f38a39a13c3439c2de1621ddb.png)
Для теста я указал время актуальности 1 минуту (чтобы долго не ждать) и остановил службу.
![image](https://habrastorage.org/getpro/habr/post_images/301/f5b/85b/301f5b85bbedcbdbe607facd443a4b86.png)
Через минуту компонент с проверкой стали красными, и мне на почту пришло письмо с уведомлением об отсутствии сигнала.
![image](https://habrastorage.org/getpro/habr/post_images/9c2/b90/1ac/9c2b901ac0b44c7b640e6b1bc5b3eb5c.png)
Все уведомления довольно гибко настраиваются, и можно получать их на email и по sms. У каждого пользователя свои контакты и свои настройки уведомлений. Отлично, эта задача решена.
Ошибки
Теперь разберёмся с ошибками. Здесь всё проще.
try {} и в catch отправляем ошибку. Есть удобный готовый метод, который из Exception выделяет сообщение, стек и т.п. и формирует ошибку.
![image](https://habrastorage.org/getpro/habr/post_images/b93/6d4/b11/b936d4b11eabe08eaa16bad4af45248b.png)
Для теста я просто вызвал throw new Exception() в теле цикла. Вот как выглядит ошибка в личном кабинете:
![image](https://habrastorage.org/getpro/habr/post_images/a1b/623/e69/a1b623e691f1aa86a7a4d81972c2353b.png)
Опять же, я получаю о ней уведомление, если мне это надо.
Надо сказать, что Zidium довольно интеллектуально понимает, что несколько ошибок являются на самом деле одной и той же. Такие ошибки соединяются в одну, что очень удобно. И спама из уведомлений тоже не будет.
Лог
Далее у нас лог. Работа с логом сделана аналогично другим библиотекам логирования, таким как nLog или Log4Net. Просто пишем что хотим, указывая уровень (важность) записи.
![image](https://habrastorage.org/getpro/habr/post_images/a07/eee/20d/a07eee20d12b8acc40224acf7b5420e0.png)
Бонус — к каждой записи лога можно прикрепить любое количество допсвойств, в которые можно поместить что угодно — например, xml. Они не замусоривают сам лог, но их всегда можно посмотреть.
Вот так выглядит лог в личном кабинете:
![image](https://habrastorage.org/getpro/habr/post_images/210/3a4/55d/2103a455dab85116bc695849802845ab.png)
Для меня это гораздо удобнее, чем читать огромные тестовые файлы.
Помимо облачного лога, Zidium на всякий случай пишет и классический файловый лог (хотя это можно отключить). Приятно, что не надо подключать ещё и другие библиотеки логирования. Всё же файловый лог может оказать полезным в крайних случаях, например, если не было связи с облаком.
Производительность
Наконец, статистика по производительности. Для этого используются “метрики”. Я замеряю общее время работы интересующих меня методов.
У метрики есть название и значение, и отправляется она так:
![image](https://habrastorage.org/getpro/habr/post_images/e08/592/b22/e08592b222536773969e408f49c2a53f.png)
В личном кабинете можно посмотреть детально всю историю метрики.
Сразу же считаются основные агрегаты за выбранный период — максимум, минимум и среднее.
![image](https://habrastorage.org/getpro/habr/post_images/67c/54b/2ca/67c54b2ca0ea0ffe46124992e905e660.png)
Жаль, нельзя скачать данные в формате xlsx или csv, это могло бы пригодиться для собственного анализа.
Ещё для метрик можно настраивать правила предупреждений о выходе значения за выбранный диапазон. Тогда о метриках тоже будут приходить уведомления. Но я это не использовал, мне полезно просто иметь статистику времени работы.
Итого
Моя служба посылает в мониторинг сигнал активности, собирает ошибки, пишет облачный лог и ведёт статистику производительности.
Я получу уведомление, если служба вдруг остановится или зависнет. Я получу уведомление, если возникнет любая ошибка.
Теперь я спокоен за сделанную мной работу и за выполнение обязательств перед заказчиком )