Русский
Русский
English
Статистика
Реклама

Новый подход к просмотру логов

Одно время, приходилось много работать с логами. Они могли быть большими и находиться на разных серверах. Требовалось не найти что-то конкретное, а понять почему система ведёт себя не так как надо. По некоторым причинам, лог-агрегатора не было.

Хотелось иметь просмотрщик логов, позволяющий, в любой момент, открыть любой файл, без скачивания на локальную машину, как команда less в linux консоли. Но при этом, должна быть удобная подсветка текста, как в IDE, и фильтрация записей по различным параметрам. Фильтрация и поиск должны работать по событиям в логе, а не по строкам, как grep, это важно когда есть многострочные записи, например ошибки со стектрейсами. Так же должна быть возможность просматривать записи сразу из нескольких файлов на одной странице, смёржив их по таймстемпу, даже если файлы находятся на разных нодах.

И я придумал как сделать такую утилиту!

Log Viewer - это небольшое web-приложение, которое работает на нодах, где лежат логи, и показывает эти логи через Web интерфейс. Это именно просмотрщик, а не агрегатор, нет никакой индексации или считывания всего лога в память, читается только та часть лога, которую пользователь смотрит в текущий момент. Такой подход позволяет почти не занимать ресурсов.

Предвижу вопросы опроизводительности типа Разве можно быстро фильтровать записи без индексации? Вплохих случаях придётся остcканировать весь лог чтобы найти хоть одну запись подходящую под фильтр. Вопервых, сканирование лога работает довольно быстро, 1Гб читается около 3,5сек, это терпимо. Вовторых, обычно известен временной интервал, вкотором ищем проблему, если задан фильтр подате, тобудет сканироваться только тачасть файла, вкоторой находятся записи относящиеся ктому времени. Найти границу временного интервала вфайле можно очень быстро бинарным поиском.

Отображение лога

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

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

Имя логгера тоже сокращено: ~.SecurityManager. Показывается только имя класса, апакет сворачивается в ~.

Фолдинг влияет только на отображение, поиск работает по оригинальному тексту. Если совпадение найдётся в сокращённой части текста, то эта часть текста автоматически появится. Также, если пользователь выделит текст и нажмёт Ctrl+C, в буфер скопируется исходный текст, без всяких сокращений.

Архитектура позволяет легко навешивать на текст подсветку или всплывающие подсказки, благодаря этому, сделаны разные приятные мелочи типа показа даты в человеческом формате, если она напечатана в виде числа:

Фильтрация

Набор фильтров зависит от формата лога. Некоторые фильтры доступны всегда, например фильтр по подстроке, а некоторые появляются если в логе присутствует поле определённого типа. Это позволяет создавать специализированные фильтры для некоторых типов полей. Например, если в логе есть поле severity, то в верхней панельке появится такой UI компонент:

Severity filter

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

Добавление фильтров из контекстного меню

Можно кликнуть назапись ивыбрать Скрыть последующие записи или Скрыть предыдущие записи, чтобы работать только сопределённой частью лога. Скрытие происходит добавлением фильтра подате.

Для сложных случаев можно задать фильтр с условием написанным на JavaScript. Такой фильтр представляет из себя функцию принимающую одну записи и возвращающую true или false.

Пример фильтра на JavaScript
function isVisibleEvent(text, fields) {    var match = text.match(/Task completed, elapsed time: (\d+)ms$/)    if (!match)        return false // Don't show events not matched the pattern            var time = parseInt(match[1])    return time > 500 // Show only events where elapsed time is more than a threshold}

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

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

Мелкие, но полезные фичи

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

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

Конфигурация

Я старался сделать конфигурацию как можно проще, чтобы всё работало из коробки. Если попросить пользователя задать формат лога, то большинство просто закроют приложение и пойдут смотреть по старинке. Поэтому формат лога распознаётся автоматически. Конечно, это работает не всегда и часто не точно. Для таких случаев можно задать формат лога вручную в файле конфигурации. Можно использовать паттерны log4j, logback или просто регексп. Если ваш лог не распознался, но вам кажется что должен создайте issue на GitHub, этим вы поможете проекту.

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

logs = [  {    path: "/opt/my-app/logs/*.log"  },  {    path: ${HOME}"/work/**"  }]

Пользователю будут доступны только .log файлы в директории /opt/my-app/logs и любые файлы в директории ~/work и её поддиректориях.

Более подробная информация в документации на GitHub.

Работа с несколькими нодами

Мёрж файлов, расположенных наразных нодах это киллер фича, ради которой изатевался проект. Как яуже говорил, файл никогда нескачивается полностью содной ноды надругую инеиндексируется. Поэтому, накаждой изнод должен быть запущен Log Viewer. Пользователь открывает webUI наодной изнод, указывает расположение логов, иLog Viewer коннектится кдругим инстансам LogViewer чтобы подгружать содержимое лога через них. Записи извсех открытых файлов мёржатся потаймстемпу ипоказываются как буд-то это один файл.

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

Наданный момент, нетUI для выбора файлов наразных нодах, приходится прописывать файлы впараметрах URL втаком виде:
http://localhost:8111/log?path=/opt/my-app/logs/a.log@hostname1&path=/opt/my-app/logs/b.log@hostname1&path=/opt/my-app/logs/c.log@hostname2
здесь каждый параметр "path" задаёт один файл, после "@" указывается хост, накотором лежит файл изапущен инстанс просмотрщика логов. Можно указать несколько хостов через запятую. Если "@" отсутствует файл находится натекущей ноде. Чтобы неиметь дела согромными URL, есть возможность задать короткие ссылки вконфигурации, вразделе log-paths = { }.

Встраивание просмотрщика в своё приложение

Log Viewer можно подключить ксвоему Java Web приложению как библиотеку, чтобы оно могло показывать пользователю свои логи. Иногда это удобней чем запуск отдельным приложением. Достаточно просто добавить зависимость на библиотеку библиотеку черезMaven/Gradle иподключить один конфигурационный класс вspring context. Всё остальное сконфигурится автоматически, log viewer сам распознает какая система логгирования используется ивозьмёт изеёконфигурации расположение иформат логов. ПоумолчаниюUI маппится на/logs, новсё можно кастомизировать. Пока автоматическая конфигурация работает только сLog4j иLogback.

Это тестировалось на маленьком количестве приложений, если у вас возникнут проблемы смело пишите в discussions на GitHub.

Что планируется сделать в будущем

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

Есть много идей по мелкому улучшению UI. Например, если в тексте встретился кусок JSON, то хочется чтобы просмотрщик умел показывать его в отформатированном виде, а не одной строкой. Хочется иметь возможность задать фильтр по severity для отдельного класса, а не сразу для всех.

Иногда нет возможности открыть порт на сервере для просмотра логов, есть только SSH доступ. Можно сделать поддержку работы через SSH. Web UI будет подниматься на локальной машине, коннектиться через SSH к серверу и запускать там специального агента. Агент будет принимать команды через input stream и возвращать нужные части лога через output stream.

Буду рад услышать фидбэк.

Источник: habr.com
К списку статей
Опубликовано: 25.01.2021 00:11:48
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Open source

Java

Отладка

Визуализация данных

Log

Logging

Kibana

Просмотр логов

Мониторинг сервера

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru