Опрос устройств печати по SNMP протоколу, пока печатает принтер


Расскажу Вам свой опыт по созданию приложения, который собирает статистику о печати устройств по SNMP протоколу. Всего более 1000 устройств и опрос выполняется в режиме реального времени, пока печатает принтер. Как это все реализовано вы узнаете из статьи.



Введение


SNMP это стандартный интернет-протокол для управления устройствами в IP-сетях на основе архитектур TCP/UDP.
С помощью SNMP не собрать информацию о пользователе, который отправил на печать файл. Кроме этого, SNMP нельзя использовать для локальных принтеров подключенных по USB.
Чтобы решить эти задачи необходимо создать клиента, который должен собирать информацию и отправлять всю статистику на сервер. В организации было так заведено, что на все клиентские машины устанавливали одинаковые ОС Linux. Соответственно клиент по сбору статистики печати написан в Linux системе, как демон (аналог службы в Windows).

Клиент сбора информации о печати


Клиент сбора печати (написан на Python) выполняет следующие задачи:
1) перехватывает сообщения из сервиса печати CUPS
2) сохраняет информацию о печати в CSV-файл
3) отправляет CSV файлы в папку на сервер по FTP

CSV файл содержит следующие поля:
1) Дата и время задания печати
2) IP-адрес или доменное имя компьютера, с которого отправлен документ на печать
3) IP-адрес или хост устройства печати
4) Идентификатор работы (Cups Job ID) — ID задания из сервиса печати CUPS
5) Наименование работы — чаще всего это имя файла
6) Имя пользователя, отправившего на печать
7) Количество страниц
8) Размер задания печати (Размер задания в КБ)
9) Статус печати (Статус задания)
10) Количество копий (Кол-во копий)
11) Кол-во копий по файлу задания — служит для более точного определения количества копий;
12) Количество страниц по SNMP-протоколу — служит для более точного определения количества страниц
13) SNMP доступно — это признак, что устройство должно непрерывно опрашиваться по SNMP-протоколу, пока документ распечатывается
14) Счетчик устройства печати на время начала печати (Значение переменной SNMP) — это проверочный счетчик, по которому определяется начало SNMP-опроса сервером

Клиент не имеет GUI-интерфейса, все настройки прописаны в конфигурационном файле
Пример конфигурационного файла:
[main]
# Основной каталог с приложением
app_directory = /opt/printwatcher

# Директория данных. Здесь располагаются данные приложения
# подготовленные к отправке файлы отчётов и служебные файлы)
stat_file_directory = /opt/printwatcher/data

# Файл, в котором хранится внутреннее состояние системы
state_file = /opt/printwatcher/data/state.pickle

# Файл, в котором хранится номер последней выполненной команды
command_state_file = /opt/printwatcher/data/command.state

# Шаблон имени файла отчёта
# Возможные именованные аргументы:
# datetime - дата создания в формате ISO 8601
# random - случайный идентификатор из 8 символов
stat_filename_template = {random}_print_jobs.csv

# Максимальный размер файла отчёта в МБ
# (при превышении начальные строки удаляются)
max_stat_file_size_mb = 10

# Разделитель CSV. Возможные значения: TAB, SPACE, SEMICOLON, COMMA
csv_delimiter = SEMICOLON

# Запускать ли поток наблюдения за очередью
start_service = start

[logging]

# Уровень логирования (DEBUG, INFO, TRACE)
level = DEBUG

# Расположение лога
log_file = /var/log/printwatcher.log

# Временный лог для загрузки после рестарта
restart_log_file = /var/log/printwatcher-restart.log

# Максимальный размер лога
# (при превышении архивируется/удаляется системной утилитой logrotate)
max_log_file_size_mb = 10

[cups]

# Директория, в которой хранятся временные файлы CUPS
spool_directory = /var/spool/cups/

# Удалять временные файлы CUPS по прошествии этого времени
# (в часах)
job_file_lifetime_hours = 48

# Не обновлять в отчёте информацию по задаче по прошествии этого времени
# (в часах)
job_info_lifetime_hours = 48

# Настройки FTP
[ftp]

host = 192.168.1.39
user = ftpuser
password = P@ssw0rd
port = 21

# Задержка перед следующей попыткой при неудачном соединении по FTP
# (в секундах)
connection_retry_seconds = 10

# Максимальная задержка, после которой прекращаются попытки соединения по FTP
# (в секундах)
connection_timeout_seconds = 3600

# Задержка между проверками файла с командами на FTP сервере
# (в секундах)
polling_interval = 30

# Каталог управления агентом на ftp-серевер
management_directory = /management

# Каталог для записи ответов агентом на ftp-серевер
response_directory = /management

# Каталог обновления агента
update_directory = /update

# Каталог в котором ищется конфигурационный файл
data_directory = /data

# Настройки SNMP
[snmp]
# следует ли опрашивать устройство по SNMP
retrieve_snmp_info = false
community = public
oid = 1.3.6.1.2.1.43.10.2.1.4.1.1
port = 161

Итак, клиент написан, теперь нужен сервер, который будет не только собирать информацию со всех клиентов, а также сервер должен отслеживать нештатные ситуации — приостановку печати, отсутствие или замятие бумаги и т.д.

Архитектура сервера сбора информации о печати


Сервер написан на языке C#, СУБД — MSSQL.
  1. Конфигуратор БД — GUI приложение, позволяющее создать и удалить БД.
    БД максимально нормализована таким образом, чтобы в основной таблице статистики не было текстовых полей для экономии места на диске.
  2. Приложение настройки сбора статистики, это GUI приложение позволяющее внести изменения в БД по SNMP-опросу, настроить OIDы, а также запускать и останавливать службу сбора статистики печати.


  3. Собственно приложение сбора и обработки статистики (служба Windows)

Сервер сбора информации о печати


Задачи сервера


  1. следить за очередью печати при обработке большого количества CSV-файлов
  2. постоянно сканировать папку на наличие CSV файлов
  3. парсить CSV-файлы и записывать информацию о печати в БД
  4. сохранение копии CSV-файлов в архив (параметр настраивается) [помогает для отладки]
  5. удаление CSV-файла после обработки
  6. ожидать разрешения конфликта
  7. вычислять выражения над значениями OID'ов
  8. раз в месяц информация выгружается в архив, а старая информация удаляется

Подробное описание алгоритмов работы внутри сервера


Прежде чем служба будет отслеживать печать в режиме реального времени, необходимо выполнить парсинг старых CSV-файлов (которые накопились, пока не работал сервер) и сохранить информацию в БД. Будем называть этот пункт «первым чтением каталога CSV-файлов», который может помочь быстро собрать статистику старой печати и сохранить в БД.

Затем служба переходит в постоянное отслеживание появления CSV-файлов в папке в отдельном потоке с интервалом 1 сек. Каждый CSV-файл обрабатывается в отдельном потоке.

Если CSV файлов в папке очень много, то на этот случай предусмотрено ограничение количества одновременных потоков чтения файлов, чтобы приложение стабильно работало. При запуске службы в папке может быть очень много CSV-файлов и эти файлы обрабатываются без SNMP-опроса, соответственно на первое чтение каталога установлено отдельное ограничение на количество потоков обработки CSV-файлов (опытным путем было установлено, что количество потоков при первом чтении CSV-файлов должно быть значительно меньше, чем количество потоков после обработки большого количества файлов).

В алгоритме предусмотрено определение IP-адреса по имени устройства и наоборот (определение имени устройства по IP-адресу) с помощью метода System.Net.Dns.GetHostEntry(). В случае отсутствия наличия связи с устройством, метод System.Net.Dns.GetHostEntry() выполняется очень долго, в связи с этим был доработан клиент, который предоставляет эту информацию в CSV. Но на сервере эта проверка осталась и метод System.Net.Dns.GetHostEntry() до сих пор является узким местом.

Сохранение информации в БД


Кроме информации о печати, в БД хранится информация для статистики:
1) время начала и окончания SNMP-опроса
2) общее количество строк в CSV-файле
3) количество строк с включенным SNMP-опросом

Предусмотрено хранение списка устройств, которые не должны опрашиваться, так называемые исключения, по которым в БД ничего не сохраняется.
После прочтения всего CSV-файла собирается информация о всех заданиях печати в объект List, которые должны быть проконтролированы SNMP-опросом. После чтения CSV-файла, он переносится в архив, если это задано настройками, и затем CSV-файл удаляется.
После того, как CSV-файл полностью прочитан проверяется, что заданы настройки опроса по SNMP-протоколу, затем устройства сортируются по приоритетам:
1) Группа по-умолчанию, в которой есть все устройства базы «ricoh_dmnx» — так называется БД системы мониторинга от производителя Ricoh, из которой мы берем список опрашиваемых устройств.
2) Устройства, которые есть в базе ricoh_dmnx, но нет в группах
3) Устройства, которые есть в базе ricoh_dmnx и есть в группах
4) Устройства, которых нет в базе ricoh_dmnx, но есть в базе нашей службы

У каждого устройства создается очередь печати, чтобы в один момент времени SNMP-опрос работал только с одним заданием печати. Таким образом, пока устройство опрашивается по SNMP-протоколу, пользователь может отправить на печать еще какой-нибудь файл и на сервер может поступить новый CSV-файл, который сохраняется сразу в БД, но опрос по нему будет выполняться после того, как закончится печать текущего документа.

При SNMP-опросе отслеживается изменение счетчика печати, статус устройства и признак ошибки устройства во время печати. Время ожидания между SNMP-опросами — 300 мс.

Подводные камни


Алгоритм сервера постоянно совершенствовался, так как возникало много разных ситуаций, при которых неверно считался счетчик. Приведу несколько советов из личного опыта:
1) Не продолжать опрос, пока устройство находится в состоянии ошибки (например: замята бумага)
2) Ошибка принтера может меняться с течением времени, поэтому таймаут SNMP-опроса не должен срабатывать в случае изменения ошибки (например, в принтере закончилась бумага, но после добавления бумаги в лоток статус принтера сменился)
3) Если на устройство печати отправляется несколько заданий одновременно, то при этом счетчик после печати первого задания:
— не изменяет статус
— изменяет счетчик

Системные OID-ы устройств печати


На основе анализа этих трех OID'ов было написано мое приложение опроса SNMP-устройств:
1) [1.3.6.1.2.1.43.10.2.1.4.1.1] — Общий счетчик устройства
2) [1.3.6.1.2.1.25.3.5.1.1.1] — Статус устройства

3) [1.3.6.1.2.1.25.3.2.1.5.1] — Ошибка устройства в процессе печати

Отчеты


Отчеты реализованы с помощью SQL Server Reporting Services.

Отчет по сравнению данных печати по месяцам




Печатные задания по пользователям




Сводный отчет по SNMP запросам




Статистика SNMP запросов




Вывод


Рад был поделиться своим опытом в реализации одного из самых сложных своих приложений, которое успешно работает начиная с 2018 года.
Особенностью в реализации проекта сбора печати была еще в том, что я не имел при себе ни одного принтера. Работал через эмулятор, который можно быстро установить и настроить (достаточно иметь MIB-файл настроек устройства печати).

В дальнейшем напишу о том, как было сделано управление агентами печати.
Источник: habr.ru