7 мая 2013 г.

Сбор логов на windows-сервере. Часть 2 - nxlog.

Продолжаем начатую здесь тему. Как я уже упоминал, syslog for windows хорош при относительно небольшом количестве источников данных (или в случае отсутствия проблемы сортировки входящего log-трафика). Если же имеется несколько десятков серверов и коммутаторов/маршрутизаторов, причем хочется раскладывать логи по полочкам папочкам, то возникают сложности. К тому же многие коммутаторы той же Cisco не умеют слать syslog-based логи на нестандартный (514/udp) порт.
nxlog представляет собой более развесистую клюкву гибкую с точки зрения работы с log-файлами альтернативу. Проект достаточно подробно документирован (HTML, PDF), в мейл-листах наблюдается какая-никакая активность. Далее рассмотрим пример работающего конфига с пояснениями, что там такого наворочено. Однако от чтения мануала нижеизложенное словоблудие не освобождает, а напротив, должно к этому мотивировать ;) .
Концепция  построения конфига nxlog похожа на рассмотренный ранее syslog for windows с учетом, конечно, модульного принципа работы этой службы. В простейшем случае нам необходимо описать входной (Input) и выходной (Output) потоки (откуда мы данные получим и куда направим), которые далее связываются в "маршрут" (Route). Каждый поток подгружает описанный в нем модуль, непосредственной работающий с данными. Модули подробно описаны в соответствующем разделе документации, имеются примеры их использования.
По пути от "Input" к "Output" данные можно "завернуть" в "Processor" - отдельная сущность для подгрузки модулей, предназначенных для внесения изменений в логи (конвертация, форматирование, поиск и так далее). 
nxlog поддерживает регулярные выражения и внутренние переменные, а также логические конструкции if/then, что позволяет очень гибко сортировать входящий поток как по источнику данных, так и по их содержимому (например, по степени критичности сообщений).
В качестве примера возьмем ту же конфигурацию сети, что и в прошлый раз. Задача та же - собрать логи с оборудования Cisco и серверов Linux. Дополнительные "плюшки" - создавать отдельный лог-файл для каждого устройства и группировать заданным образом файлы по папкам.
define ROOT C:\Program Files (x86)\nxlog
define LOGDIR C:/nxlog

Moduledir %ROOT%\modules
CacheDir %ROOT%\data
Pidfile %ROOT%\data\nxlog.pid
SpoolDir %LOGDIR%
LogFile %LOGDIR%\nxlog.log

<Input UDP_flow>
    Module im_udp
    Port 514
    Host 0.0.0.0
    SockBufSize 15000000
</Input>

<Output logfile>
    Module om_file
    CreateDir true
    Exec $ip = $MessageSourceAddress;

##cisco switches
    Exec     if $ip =~ /10.10.10.(101|102|103|104|105|141|142|143|144|145)/ \
            {     $type = "FloorSwitches"; \
                $type2 = "test"; }
   
## cisco inet routers
    Exec     if $ip =~ /10.10.10.1(09|10|49|50)/ \
            $type = "InetRouters";

## linux firewalls
    Exec     if $ip =~ /10.10.11.(3|4)/ \
            $type = "LinuxFW";

## linux servers
    Exec     if $ip =~ /10.10.10.(12|13)/ \
            $type = "LinuxServers";

### Output folder/file           
    File "%LOGDIR%/"   $type   "/"   $ip   ".log"
</Output>

<Route default>   
    Path UDP_flow => logfile
</Route>   
Итак, сначала определяются переменные окружения - корневая директория, место хранения лог-файлов и прочее. Далее описывается входной поток <Input>, названный UDP_flow - мы используем входной модуль im_udp с описанными параметрами. Так как видоизменять входящие данные не требуется, потоков <Processor> нет, сразу переходим к потоку <Output> с названием logfile. Внешне он выглядит сложнее, однако по сути все просто: 
Во-первых, мы используем выходной модуль om_file с описанными параметрами (список всех доступных параметров и описание их действий смотри в мануале). 
Во-вторых, мы используем возможность Nxlog-а исполнять внутренние команды (также возможен вызов и внешних процедур или программ) через директиву Exec. 
В-третьих, мы пользуемся служебной переменной $MessageSourceAddress, которая автоматически заполняется входным модулем im_udp. Так как логи передаются построчно, для каждого момента времени мы точно знаем, кто именно прислал данную информацию на 514/udp.
В-четвертых, пользуясь поддержкой регулярных выражений и логических конструкций, мы описываем желаемую логику сортировки - группируем источники по ip-адресам и определяем переменную $type. Переменная $type2 в ##cisco switches лишняя  и оставлена для того, чтобы показать, как описываются блоки данных (Statements).
В-пятых, описываем файл, который будет записываться та или иная входящая строка. Путь конкатенируется исходя из определнных выше переменных. Как было отмечено выше, логи поступают и обрабатываются построчно, поэтому для каждой строки значения $ip и $type могут изменяться.
Наконец, описываем "маршрут" движения данных - <Route>. В нашем случае он простой 
Path UDP_flow => logfile
вход - выход.
Таким образом, в папке LOGDIR создается иерархия папок, внутри которых (согласно правилам сортировки) располагаются лог-файлы удаленных устройств.
К сожалению, встроенного механизма rotate у nxlog нет. Однако модуль om_file предоставляет процедуру rotate_to(), с помощью которой можно этот вопрос порешать.
В своей работе я остановился на nxlog, однако syslog for windows также нашел себе применение в более мелких проектах. Оба инструмента хороши, каждый имеет свои сильные стороны - выбор есть всегда.