Как стать автором
Обновить

CutTheLog – когда он слишком большой

Уровень сложностиСредний
Время на прочтение3 мин
Количество просмотров2.5K
Log в переводе с английского «бревно»
Log в переводе с английского «бревно»

Парсинг логов – типовая задача для системных администраторов и девопсов. Обычно это регулярная операция. Данные постоянно пишутся в конец файла, поэтому периодически его надо открывать и обрабатывать новые записи. В процессе нужно искать место, где мы закончили чтение в прошлый раз. Давайте автоматизируем этот поиск так, чтобы он не требовал просмотра лога с самого начала.

Первое, что приходит на ум, – запомнить позицию в файле, на которой мы закончили. Её возвращает функция tell. На следующей итерации перейдём сразу на эту позицию и продолжим чтение оттуда. Это делает функция seek практически бесплатно.

Схема простая и рабочая, но при ротации лога возникают проблемы. Во-первых, переход за границу файла не приведёт к ошибке, просто при чтении мы получим пустые данные. Значит, перед переходом надо проверить, что сохранённое значение не превышает размер файла, и если это не так, читать лог с начала. Даже в таком случае после ротации может записатся достаточно данных для успешного прохождения проверки. Тогда мы как ни в чём не бывало продолжим «с места, где закончили» и пропустим кусок данных.

Есть способ усовершенствовать алгоритм: запоминать смещение не конца файла, а начала последней прочитанной строки и её значение. В этом случае мы также перейдём на закешированную позицию, а потом прочитаем строку и сравним её с сохранённой. Если значения совпали, продолжаем чтение дальше. Если различаются, возвращаемся к началу файла. Так как в каждой строке лога обычно есть метка времени, успешное прохождение проверки после ротации практически невозможно.

Я реализовал эту идею в небольшом Python модуле. Он называется cutthelog. В нём есть единственный класс CutTheLog, позволяющий открыть файл и выполнить описанную проверку. Как результат он возвращает итератор по непросмотренным строкам лога. Для создания объекта передаём путь файла и опционально смещение и значение строки, на которой мы закончили чтение. Выглядит это так:

import sys
from cutthelog import CutTheLog

ctl = CutTheLog('/var/log/syslog', offset=7777, last_line=b'...')
with ctl as line_iter:
  print('Starting at:', ctl.get_position(), end='', file=sys.stderr)
  for line in line_iter:
		print(line.decode(), end='')
print('Ending at:', ctl.get_position(), end='', file=sys.stderr)

Строки лога имеют тип bytes, так как даже на моей дескпотной убунте в логе /var/log/syslog есть символы, которые нельзя декодировать в юникод. Каждая строка возвращённая итератором, обновляет позицию внутри объекта. Значит, мы можем читать произвольное количество строк, а не только до конца файла. В классе есть методы для сохранения позиции в кеш на диске и чтения её оттуда.

Модуль сам по себе является утилитой командной строки. Она выводит на консоль содержимое файла, сохраняя позицию его конца в кеше. При следующем запуске печатаются только строки, которые были записаны после предыдущего чтения. Выглядит это так:

$ echo -e "one\ntwo\nthree" > example
$ cutthelog example
one
two
three
$ cutthelog example
$ echo -e "four\nfive\nsix" >> example
$ cutthelog example
four
five
six
$ cutthelog example
$ echo -e "seven\neight\nnine\nten\neleven\ntwelve" > example
$ cutthelog example
seven
eight
nine
ten
eleven
twelve

Кеш хранится в файле .cutthelog в домашней директории пользователя. Запуск под другим пользователем выведет файл полностью. Путь до кеша можно задать вручную опцией -c/--cache-file.

Код модуля находится на github. Python пакет доступен на pypi. Надеюсь, они будут вам полезны.

Теги:
Хабы:
Если эта публикация вас вдохновила и вы хотите поддержать автора — не стесняйтесь нажать на кнопку
Всего голосов 4: ↑1 и ↓30
Комментарии19

Публикации

Истории

Работа

Data Scientist
82 вакансии
DevOps инженер
48 вакансий
Python разработчик
137 вакансий

Ближайшие события

12 – 13 июля
Геймтон DatsDefense
Онлайн
14 июля
Фестиваль Selectel Day Off
Санкт-ПетербургОнлайн
19 сентября
CDI Conf 2024
Москва
24 сентября
Конференция Fin.Bot 2024
МоскваОнлайн