понедельник, 10 сентября 2018 г.

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

Работа с журналом регистрации в формате SQLite внешними средствами на примере мониторинга изменений в конфигурации базы данных.
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
Источник: здесь

Комментариев нет:

Отправить комментарий