Мониторинг журнала регистрации при помощи Powershell




Работа с журналом регистрации в формате SQLite внешними средствами на примере мониторинга изменений в конфигурации базы данных.

Немного о Powershell

Powershell — расширяемое средство автоматизации от Microsoft, состоящее из оболочки с интерфейсом командной строки и сопутствующего языка сценариев. 
PowerShell версии 2.0 — неотъемлемый компонент в составе Windows 7, Windows 8 и Windows Server 2008 R2 и др. Т.е. доустанавливать обычно ничего не надо — все уже есть в системе.
Требуемую функциональность для своих задач можно наращивать при помощи уже готовых скриптов-командлетов. Базовых операций очень много, изобретать велосипеды не обязательно. В открытом доступе можно найти множество готовых решений, созданных другими пользователями, не только Microsoft (кстати, тоже бесплатно).

Про журнал регистрации и его мониторинг

Зачем мониторить журнал регистрации? 
Ну, например, можно делать выборку последних ошибок за час и отправлять их на рассмотрение службе поддержки. Или сигнализировать о частом появлении определенных типов ошибок. Или мониторить работоспособность регламентных заданий.
Одна из задач — получение оповещений о том, что конфигурация БД изменилась. На основе этого события можно запускать, например, сохранение конфигурации из SQL, можно отправлять уведомление разработчикам, чтобы они были в курсе и не теребили владельца продукта вопросами вида "а ты накатил мои изменения?". Давайте реализуем этот функционал. 

Уже достаточно давно платформа 1С предоставляет возможность вести ЖР в формате SQLite. Одним из преимуществ формата является быстрый поиск по настраиваемым фильтрам. Сразу оговоримся, что далее мы работаем с ЖР именно с этим форматом. Как узнать, что у вас новая версия? Достаточно взглянуть на его начинку, файл журнала находится в 1Cv8.lgd. Уже в первых строках содержится ответ:

 

При обновлении конфигурации базы данных в ЖР попадает событие "Изменение конфигурации базы данных". Выглядит это примерно так:

 

Как же представлено это событие в самой базе SQLite? Откроем файл базы каким-нибудь средством просмотра. Воспользуемся DB Browser for SQLite (есть portable-версия)
 
Открываем базу (1Cv8.lgd) и находим в EventCodes "странное" событие "_$InfoBase$_.DBConfigUpdate". Именно оно отвечает за фразу "Изменение конфигурации базы данных". Учтем, что код события разнится от журнала к журналу для разных баз.

Теперь попробуем найти в основной таблице EventLog все события с таким кодом (в нашем примере 101) и заодно узнаем пользователя, который сделал изменения (данные в таблице UserCodes). Воспользуемся "консолью запросов" DB Browser:

 

Как видим нашлась всего 1 запись. Хотя могло быть сколько угодно. Запрос выполнен за 3.2 секунды для 200-мегового лог-файла, лежащего в локальной сети. Тот же запрос для файла на SSD-диске выполняется 1.7 секунды.
Для задачи уведомлений, нам не обязательно знать все моменты обновления, поэтому если ограничить выборку определенной датой, то запрос выполняется в разы быстрее: доли секунды.

Давайте попробуем сделать выборку при помощи скрипта на Powershell. Находим первый попавшийся PSSQLite PowerShell Module 
для работы с SQLite. Пакет работает на Powershell 2.0, не требует инсталляции, достаточно просто скопировать его в папку и он готов к работе.
Тут же прекрасная документация по работе с методами, разобраться можно за считанные минуты. 
Искомые события найдем при помощи метода Invoke-SqliteQuery:

    ##### подключить модуль
Import-Module .PSSQLite

## ищем событие, отвечающее за обновление базы данных
$db_update_string = '"_$InfoBase$_.DBConfigUpdate"'
try {
$data_row = Invoke-SqliteQuery -DataSource $path_to_ZhR -as "DataRow" -Query "select code from EventCodes where name = '$db_update_string'"
}
catch {
show_message("Ошибки при получении данных из базы: $error")
exit 1
}

$db_update = $data_row.Code
if (!$db_update)
{
show_message("нет события обновления БД")
exit 0
}
show_message("Код события обновления БД: <$db_update>")

$query = "SELECT connectid,`
date as original_date,`
datetime(date/10000-$utc_seconds,'unixepoch') as date ,`
comment, `
UserCode, `
UserCodes.uuid, `
UserCodes.name as user `
FROM EventLog `
left join  UserCodes on  EventLog.userCode = UserCodes.code`
where eventcode=$db_update `
and date>$date_content `
ORDER BY date asc `
LIMIT 10"

try {
$data_row = Invoke-SqliteQuery -DataSource $path_to_ZhR -as "DataRow" -Query $query
}
catch {
show_message("Ошибки при получении данных из базы: $error")
exit 1
}

if (!$data_row)
{
show_message("Не найдено обновлений")
exit 0
}

    
Итак, мы нашли нужные события, теперь надо отправить их куда-то. Например, в slack

Отправка в Slack при помощи PowerShell

С отправкой в слак все еще проще с точки зрения реализации. Создана простейшая функция по отправке сообщения в канал. Нужно знать только token.

function SendToSlack {
param (
[Parameter(Mandatory=$true, Position=0)]$Text,
$token="xxxxx",
$Username,
$Proxy ,
$Channel
)
$max_dlina=500
if ($text.length -gt $max_dlina)
{
$Text = $Text.Substring(0,$max_dlina)+"..." # ограничим длину сообщения, чтобы слак смог принять
}
$postSlackMessage = @{token=$token;channel=$Channel;text=$Text;username=$username;as_user=$true}
$response = Invoke-RestMethod -Uri https://slack.com/api/chat.postMessage -Body $postSlackMessage -Proxy $Proxy
show_message "Результат отправки: $response"

}

Код прост, но есть ложка дегтя — для выполнения метода Invoke-RestMethod требуется powershell версии 3.0. Для Windows server 2012 это не проблема, он уже установлен, а вот обладателям более ранних версий операционной системы придется доставить соответствующие пакеты. В частности, на windows server 2008 r2 (sp1) надо поставить Windows Management Framework 3.0 (Windows6.1-KB2506143-x64.msu) 

Не Slack-ом единым

Для тех, кто предпочитает уведомления просто в почту, достаточно воспользоваться командлетом Send-MailMessage. Он, кстати, работает и на версии 2.0.

    Send-MailMessage -From "1C-reports@domain.ru" -To "1C-developers@domain.ru" -Subject "обновление базы" -Body "сообщение"

Правда, возможно, тут придется поколдовать с авторизацией для вашего домена. 
Никто не запрещает придумать свои способы оповещения через другие мессенджеры или каналы связи.

Про права

Сам журнал регистрации не требует особых прав на доступ к нему — достаточно просто прав на чтение файла. А вот powershell-скрипты должны быть разрешены во избежание получения сообщения "…так как выполнение скриптов запрещено для данной системы".
Это делается один раз командой

    ## Restricted (Запрещено, по умолчанию) Сценарии не запускаются.
## Allsigned (Все подписанные) Запускаются только подписанные сценарии.
## RemoteSigned (Удаленные подписанные) Разрешен запуск локальных сценариев, прочие сценарии должны быть подписаны.
## Unrestricted (Без ограничений) Запускаются все сценарии.
set-executionpolicy remotesigned

Кстати, о доступе к файлу журналу. Наш скрипт не мешает штатной работе 1С. Можно подключаться к "боевому" файлу журнала. Проводили эксперимент, чтобы проверить влияние механизма на работу 1С. Запускали фоновое задание, строчащее в ЖР по сотне сообщений в секунду. Одновременно стартовали скрипт — все отрабатывается без ошибок. База клиент-серверная, скрипт стоит локально на сервере. Никто никому не мешает

Что в итоге

Сам powershell-скрипт можно запускать через планировщик windows от имени сервисной учетной записи, встраивать в сборочные линии и находить другие применения. 
За рамками статьи остались нюансы превращения времени unix в нормальные человекопонятные даты и учет часовых поясов. Эти моменты можно посмотреть в самом скрипте, который прикладывается к статье. Также скрипт умеет "запоминать" последнее время работы, пишет в лог, что он делал и    отправляет сообщения в Slack. В архиве приложена и сама библиотека для работы с SQLite

Ссылки

7 Comments

  1. Timur.V

    Вы подключаетесь к файлу журнала регистрации, который не подключен к базе 1с. Верно?

    Reply
  2. blackhole321

    Почему Вы рекомендуете запускать скрипт в планировщике из под системной учётной записи (я так понимаю Вы имели ввиду system)?

    Reply
  3. blackhole321

    И да, Set-ExecutionPolicy надо выполнять из под аккаунта с административными привилегиями

    Reply
  4. user768334

    (1) Спасибо за вопрос!

    На самом деле можно подключаться к ЛЮБОМУ файлу журнала. Проводили эксперимент, чтобы проверить работоспособность механизма. Запускали фоновое задание, строчащее в ЖР по сотне сообщений в секунду. Запускали скрипт — все отрабатывается без ошибок. База клиент-серверная, скрипт стоит локально на сервере.

    Никто никому не мешает

    Reply
  5. user768334

    (2) Про рекомендации речь не идет, написано, что можно. Лучше, чтобы это была какая-то сервисная учетка.

    Reply
  6. blackhole321

    (5)Ну если не сложно, по моему мнению лучше-бы поправить в статье, а то кто-нибудь так и будет из под system запускать

    Reply
  7. artbear

    ОФФ/2 У powershell есть несколько проблем использования:

    + Язык довольно таки необычен и обучиться не так просто

    + если возвратиться к нему после некоторого перерыва неиспользования, сложно восстановить знания и приходится делать много усилий.

    +а слишком часто пользоваться им не получается, т.к. мы все-таки 1С-специалисты, а не чистые администраторы

    Это результаты моего опыта и несколько моих коллег.

    Поэтому последние годы мы пересели с powershell на OneScript 🙂 и активно развиваем его инфраструктуру.

    PS о моих компетенциях на Powershell — занимался им не один год.

    Делал на Powershell целый продукт для одной известного розничной сети — полностью автоматическое обновление розничных точек для 1С 7.7 🙂 по всей стране — 3,5 тысячи точек.

    С авто-тестами, BDD (Pester) и все такое 🙂

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *