|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
Есть множество (сотни, тысячи) log-файлов, содержащих дату (yyyy-mm-dd), время (hh:mm:ss) и сообщение, все сообщения однострочные. Нужен скрипт, который выведет все логи за определенный период (например за последние 24 часа или за период с d1 по d2). Сейчас я сделал все "ленивым" способом: по очереди обрабатываю все файлы, считываю их построчно, добавляю во временный массив строки, дата/время которых соответствуют периоду, а в конце просто сортирую временный массив и вывожу его. Но напрашивается способ все это оптимизировать. Поскольку log-файлы заполняются последовательно (то есть уже отсортированы по дате), то можно очень сильно сократить требования к памяти и заодно ускорить обработку. Алгоритм я вижу следующим. Открываю файл, считываю строку, считываю из нее дату. Если дата меньше нужного периода, то повторяю со следующей строкой. Если дата вошла в нужный интервал — запоминаю в индексном указателе файл, смещение текущей строки и дату, на которую указывает данное смещение, после чего закрываю файл. Затем повторяю то же самое со следующим файлом. При добавлении в индексный указатель новой записи сравниваю с другими индексами, чтобы вставить ее в нужное место (чтобы индексный указатель был упорядочен по дате). Когда все файлы обработаны, то начинаю обрабатывать индексный указатель, начиная с самого минимального элемента. После считывания строки по указателю определяю следующую дату и перестраиваю индекс. И так до тех пор, пока дата не превысит заданный период или все файлы не будут выведены полностью. Точность сравнения будет до секунд, в пределах одной секунды записи одного файла будут неразрывны (то есть не будут перемешиваться записи с разных файлов) В индексном указателе будет высокая интенсивность вставок, поэтому его лучше делать связанным списком. Тем не менее будет очень много рутинной возни с пересчетом и перестановкой индексов. Может быть это можно как-то улучшить? ... |
|||
:
Нравится:
Не нравится:
|
|||
26.04.2021, 15:22 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
По сути тебе не сортировка нужна, а слияние. Выбираешь нужный кусок первого лога в один массив, кусок второго во второй - делаешь слияние (в один проход). Затем также 3 и 4 лог, затем слияние обоих результатов. Принцип как у сортировки слиянием . Этот алгоритм можно легко распараллелить. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.04.2021, 15:33 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
Если делать слияние, то это уже будет расход памяти (в которой будет храниться итоговый массив). А я хочу вообще память на это не расходовать, в памяти будет только индексный указатель на текущие смещения в файлах и соответствующие им даты. Мне просто нужно реализовать правильную обработку сдвига указателей (в пределах секунды по строкам внутри файла, за пределами секунды по самим файлам). ... |
|||
:
Нравится:
Не нравится:
|
|||
26.04.2021, 15:42 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
Alibek B. в памяти будет только индексный указатель на текущие смещения в файлах и соответствующие им даты. Мне просто нужно реализовать правильную обработку сдвига указателей (в пределах секунды по строкам внутри файла, за пределами секунды по самим файлам). Двигать указатели никуда не надо, т.к. сама строка в логе никуда не сдвигается. В остальном алгоритм это никак не меняет, вместо массивов строк храни массивы структур с полями: {Дата, Номер лога, Смещение} PS Это как часто надо делать? Если часто, то может есть смысл в БД переливать постоянно, например раз в минуту, а как потребуется - быстро выбрать. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.04.2021, 15:50 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
То есть примерно так. Например мне нужно вывести логи за период с 2021-04-26 01:02:03 по 2021-04-26 08:00:00. Делаю инициализацию, открываю все файлы, считываю в индексный указатель смещения с датой 2021-04-26 01:02:03 и более, но не больше 2021-04-26 08:00:00. По итогам инициализации у меня есть упорядоченный по дате индекс. Нахожу в индексе минимальный файл, у которого смещение указывает на 2021-04-26 01:02:03, вывожу все строки с этой датой (одновременно с этим обновляя смещение и дату в индексе). Затем повторяю со всеми файлами индекса, у которых смещение указывает на 2021-04-26 01:02:03. По завершению выведены все записи на момент 2021-04-26 01:02:03. Затем нахожу в индексе следующую дату, которая будет старше 2021-04-26 01:02:03 — например это будет 2021-04-26 01:02:05. А повторяю до тех пор, пока не дойду до 2021-04-26 08:00:00. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.04.2021, 15:53 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
Dima T PS Это как часто надо делать? Если часто, то может есть смысл в БД переливать постоянно, например раз в минуту, а как потребуется - быстро выбрать. Эпизодически. Это не постоянная потребность, а скорее инструмент траблшутинга, будет необходим от случая к случаю. Отдельные лог-файлы как раз удобны (у каждого объекта свой лог), но иногда нужно делать "сквозной" просмотр или поиск. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.04.2021, 15:54 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
Alibek B. То есть примерно так. Например мне нужно вывести логи за период с 2021-04-26 01:02:03 по 2021-04-26 08:00:00. Делаю инициализацию, открываю все файлы, считываю в индексный указатель смещения с датой 2021-04-26 01:02:03 и более, но не больше 2021-04-26 08:00:00. По итогам инициализации у меня есть упорядоченный по дате индекс. Нахожу в индексе минимальный файл, у которого смещение указывает на 2021-04-26 01:02:03, вывожу все строки с этой датой (одновременно с этим обновляя смещение и дату в индексе). Затем повторяю со всеми файлами индекса, у которых смещение указывает на 2021-04-26 01:02:03. По завершению выведены все записи на момент 2021-04-26 01:02:03. Затем нахожу в индексе следующую дату, которая будет старше 2021-04-26 01:02:03 — например это будет 2021-04-26 01:02:05. А повторяю до тех пор, пока не дойду до 2021-04-26 08:00:00. По сути это тоже слияние, но не из двух источников, а больше. Можно делать слияние любого количества источников, в твоем случае открыть N файлов с логами, в каждом встать на первую подходящую запись и затем найти файл с наименьшим временем, записать из него, затем снова найти с наименьшим временем и т.д. Так расход памяти минимальный, но возрастает нагрузка на проц, т.к. каждый раз надо искать минимум среди всех логов. Попробуй, может эти тормоза окажуться незначительными. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.04.2021, 18:19 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
Alibek B. Алгоритм я вижу следующим. Открываю файл, считываю строку, считываю из нее дату. Если дата меньше нужного периода, то повторяю со следующей строкой. Если дата вошла в нужный интервал — запоминаю в индексном указателе файл, смещение текущей строки и дату, на которую указывает данное смещение, после чего закрываю файл. Затем повторяю то же самое со следующим файлом. При добавлении в индексный указатель новой записи сравниваю с другими индексами, чтобы вставить ее в нужное место (чтобы индексный указатель был упорядочен по дате). Когда все файлы обработаны, то начинаю обрабатывать индексный указатель, начиная с самого минимального элемента. После считывания строки по указателю определяю следующую дату и перестраиваю индекс. И так до тех пор, пока дата не превысит заданный период или все файлы не будут выведены полностью. Точность сравнения будет до секунд, в пределах одной секунды записи одного файла будут неразрывны (то есть не будут перемешиваться записи с разных файлов) В индексном указателе будет высокая интенсивность вставок, поэтому его лучше делать связанным списком. Тем не менее будет очень много рутинной возни с пересчетом и перестановкой индексов. Может быть это можно как-то улучшить? Мне кажется в топике есть как-бы 2 пути решения. 1) Это следовать твоим указаниям по реализации. Я думаю вряд-ли читатели форума захотят это делать. Это похоже на ТЗ. Не стиль форума. Да и не захотят все делать так. Вот если ты напишешь макет и предложишь улучшить или пофиксить баг - то пожалуй да. 2) Решить задачу так как ее решают админы и девопсы. Как-то так Код: plaintext 1. 2. 3.
Будет медленно. Нудно. Но сработает. Далее можно кешировать или автоматизировать и скриптовать бесконечно. Можно резать логи на месячные. Сутошные. Часовые партишены и раскладывать по фолдерам для пущей скорости. И тогда выборка сводится просто к навигации в файловой системе. Это дешево. Почти нулевые расходы. Строить индексные структуры для данной задачи - это конечно интересно но мне кажется подобная задача уже была решена например в Elastic Search. Есть смысл поднять эластик хотя-бы в докере и попробовать натравить его на логи. Будет быстро + текстовые возможности поиска. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.04.2021, 18:22 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
mayton, эта, может ему это все во что нибудь типа sqlite загрузить? // ... |
|||
:
Нравится:
Не нравится:
|
|||
27.04.2021, 16:24 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
Можно. Если ему не жалко в памяти держать свои драгоценные пета-байты логов. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.04.2021, 16:45 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
mayton Можно. Если ему не жалко в памяти держать свои драгоценные пета-байты логов. а шо там в памяти держится? была какая то штука логпарсер https://en.wikipedia.org/wiki/Logparser я ей както в сайбез все сгружал, щас почитаю как ... |
|||
:
Нравится:
Не нравится:
|
|||
27.04.2021, 16:53 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
ааа, делал из логов csv файл и интерактив скл-ем cгружал в бд. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.04.2021, 16:57 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
чем больше читаю, тем меньше мне эта идея нравится ))) греп там еще шото делает. окончательно передумал Код: python 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71.
... |
|||
:
Нравится:
Не нравится:
|
|||
27.04.2021, 17:04 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
На слуху у меня такое ключевое слово как Splunk. Я с ним лично не работал, но вроде как в ентерпрайзе - его любят https://www.splunk.com/ Считается морально устаревшим. Ему на замену рекомендуют связку Elastic + Kibana. https://www.elastic.co/elastic-stack В Кибане - роскошные средста визуализации. Можно временные диаграммы ошибок строить. Также стек содержит готовые шаблоны для захватывания логов nginx, apache http e.t.c. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.04.2021, 18:29 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
Как-то это все не то. Если бы это был кровавый энтерпрайз, то да, я бы уже давно грузил бы логи в базу данных или в Elastic. Но это небольшая вспомогательная хотелка, нынешний формат (текстовый лог на объект) устраивает в 99% случаев и лишь изредка нужен "сквозной поиск" или "сквозной просмотр". И мне интересно это сделать минимальными ресурсами, мне кажется красивым сделать алгоритм, который не требует для своей работы больших вспомогательных буферов памяти. И пока что я не вижу дефектов в описанном мной выше алгоритме. То есть вначале находим во всех файлах самую раннюю запись, подходящую под критерии вывода (причем это можно делать как последовательно, так и параллельно). Затем по найденным результатам находим самую раннюю запись, выводим ее и ищем следующую раннюю запись. Поскольку во всех файлах записи упорядочены, то после первого сканирования повторные сканирования больше не нужны, достаточно правильно обновлять указатели в файлах (чтобы они всегда были упорядочены по возрастанию). Если кто-то укажет на ошибки в алгоритме или более оптимальный алгоритм, то буду рад. Но как натравить на подобную задачу современные инструменты, я и сам знаю. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.04.2021, 20:58 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
Покажи имена твоих файлов. Есть-ли в имени намёк на искомые данные? ... |
|||
:
Нравится:
Не нравится:
|
|||
27.04.2021, 21:30 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
Имена файлов это просто целое число. (это логи телеграм-бота, для каждого пользователя отдельный лог) ... |
|||
:
Нравится:
Не нравится:
|
|||
27.04.2021, 21:55 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
Жаль. Ну тогда их надо всех перелопатить и проиндексировать. Можно следовать твоему алгоритму. Строить BRIN-подобные индексы для текста. Но возникает вопрос структуры данных. Где это хранить и как обновлять этот индекс. Если у тебя с телеграм бота сливаются сведенья по разным потокам и в одно время - то надо как-то усложнять этот индекс чтобы он объединял данные. И можно просто сделать как я предложил. Обрабатывать все файлы и переливать их в структуру каталогов типа yyyy/mm/dd/hh/mm/ss. Файлы можно даже не объединять. Пускай в одной секунде будет несколько разных источников. Парсинг и grep этой секунды пройдет очень быстро. Тоесть моя задача сводится к сплиту всех файлов на такие короткие секундные фрагменты. Внешний вид CLI может выглядеть как-то так: Код: sql 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
27.04.2021, 22:43 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
все же просто и шаблонно. запустить spark, вычитать файлы в spark датафрейм, сохранить в parquet табличку с датой-время (yyy-mm-dd-hh24) в качестве партиции. на ноутбуке с ssd это в пределах часа-двух на 100 гб логах. после этого кверить из колончатой структуры паркета, указывая четкую партицию, будет очень быстро. причем кверить можно будет прямо в sql языке. новые логи также превращать в parquet и докидывать в папку с новой датой (в новую партицию). как вариант скачать докер с zeppeline и записать все это в notebook и настроить в нем же шедулинг, визуализацию с бэкджеком. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.04.2021, 08:12 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
mayton Обрабатывать все файлы и переливать их в структуру каталогов типа yyyy/mm/dd/hh/mm/ss. Нет. Поиск логов в конкретном файле (для конкретного пользователя) — гораздо более частая и нужная задача, поэтому логи и партицируются по айди пользователя. В дальнейшем может быть добавлю ротацию логов по годам или месяцам, но пока такой необходимости нет. Сквозной поиск по всем логам нужен намного реже, чтобы под него менять структуру логов. У простого текстового последовательного лога есть свои преимущества, поэтому грузить их в реляционную или документную базу данных я пока не планирую. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.04.2021, 09:57 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
Alibek B. mayton Обрабатывать все файлы и переливать их в структуру каталогов типа yyyy/mm/dd/hh/mm/ss. Нет. Поиск логов в конкретном файле (для конкретного пользователя) — гораздо более частая и нужная задача, поэтому логи и партицируются по айди пользователя. В дальнейшем может быть добавлю ротацию логов по годам или месяцам, но пока такой необходимости нет. Сквозной поиск по всем логам нужен намного реже, чтобы под него менять структуру логов. У простого текстового последовательного лога есть свои преимущества, поэтому грузить их в реляционную или документную базу данных я пока не планирую. А мы можем обогатить логи, добавив к дате ID пользователя? Например. Код: sql 1. 2.
Ничего не меняется в остальном и мой алгоритм слияния остается в силе. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.04.2021, 10:43 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
Можем. Но я имею ввиду другое, мне как раз удобно иметь раздельные логи по каждому пользователю. (к тому же идентификаторы далеко не трехзначные и съедают ширину экрана) (а также имеют переменную длину и нарушают колонки при просмотре) ... |
|||
:
Нравится:
Не нравится:
|
|||
28.04.2021, 13:08 |
|
Объединение логов в общий журнал и вывод в хронологическом порядке за интервал
|
|||
---|---|---|---|
#18+
Alibek B., колхозить однопоточную обработку глупо. то о чем ты говоришь делается ровно двумя командами val df = spark.read().format("csv").option("delimiter", " ").option("header", "false").load(dir_path) ds.filter("user='shit'").show(); и это будет многпоточное чтение. если надо по папкам (партициям) разложить, тоже простенькая конструкция. и сохранить разложенное, хоть в json, хоть в xml. хотя смысла перекладывать в формат отличный от parquet/orc нет никакого. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.04.2021, 15:26 |
|
|
start [/forum/topic.php?fid=16&msg=40066407&tid=1339670]: |
0ms |
get settings: |
9ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
141ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
60ms |
get tp. blocked users: |
1ms |
others: | 15ms |
total: | 264ms |
0 / 0 |