Задача. Архиватор логов
Неотъемлемая часть любого промышленного приложения — это его логи. Туда попадают записи о всех важных событиях в жизни приложения, например ошибках, скорости и результатах выполнения пользовательских запросов. Зачастую чтение логов — единственный способ разобраться с внезапно возникшей в продакшене неведомой проблемой, или посчитать какую-то статистику о работе приложения.
За день приложение под хорошей нагрузкой может генерировать десятки гигабайт логов. Все эти логи хочется хранить вечно, а значит, их надо сжимать.
Обычно для этих целей используются алгоритмы сжатия общего назначения — например, gzip. Но можно ли сжимать лучше? Наверное да — ведь логи имеют специфичный формат записей и множество повторяющихся элементов. Ваша задача — продемонстрировать, что это возможно.
Задача
Разработать приложение для архивации логов в заданном формате (см. конец этого документа). Это должно быть консольное приложение, имеющее два режима работы: сжатие и разжатие.
При запуске с двумя аргументами приложение должно запускаться в режиме сжатия: dotnet LogPacker.dll <input_file> <output_file> Первый аргумент задает путь до исходного лог-файла. Второй аргумент задает путь до файла, куда вы запишете сжатые данные.
При запуске с тремя аргументами, где первый равен -d, приложение должно запускаться в режиме разжатия: dotnet Kontur.LogPacker.dll -d <input_file> <output_file> Здесь второй аргумент задает путь до сжатого файла, сформированного вашим приложением, а третий аргумент — путь до разжатого файла.
Требования и ограничения
Внимание! Чтобы соблюсти все базовые требования к решению, рекомендуем воспользоваться шаблоном: https://github.com/DQKrait/Kontur.LogPacker/tree/master Там также есть набор простейших тестов и утилита для запаковки решения в архив перед отправкой на проверку.
Внимание! Для выполнения задания вам понадобится .NET Core SDK 2.1 и среда разработки Visual Studio 2017 или JetBrains Rider. Пробную версию JetBrains Rider можно скачать тут: https://www.jetbrains.com/rider/
Функциональные требования: После цикла сжатие-разжатие файл должен быть побайтово равен исходному. Алгоритм должен корректно работать на логах, где строки имеют другой формат, а также на данных, вообще не являющихся логами (в общем случае это просто случайные бинарные данные). Требований по качеству сжатия в таком случае нет, но требования по скорости сжатия сохраняются. Качество сжатия: на произвольных лог-файлах заданного формата размер сжатых данных должен быть меньше, чем при использовании gzip (здесь и далее имеется в виду стандартная реализация из .NET Core: GZipStream с CompressionLevel.Optimal). Ваш архиватор должен выигрывать хотя бы 1 процентный пункт (если gzip сжимает файл до 25% исходного размера, у вас должно получаться 24% или ещё меньше). Скорость сжатия: на любых данных время работы вашего алгоритма не должно превышать время работы gzip более чем в два раза. Аналогично со скоростью разжатия. Потребление оперативной памяти: объем потребляемой оперативной памяти не должен зависеть от размера входных данных и на любых входных данных не должен выходить за разумные пределы (100-200 МБ).
Загрузка процессора: архивация логов не должна мешать другим работающим на машине приложениям. Поэтому ваш архиватор должен работать в один поток. Решение может создавать временные файлы, но их суммарный размер не должен превышать размер входного файла, и они должны удаляться до завершения процесса архиватора. Все временные файлы должны находиться в рабочей директории приложения (т. е. если вы будете указывать только имя файла, без директории, всё сработает как надо).
Требования к оформлению: Решение должно представлять собой консольное приложение на .NET Core 2.1. Нельзя использовать внешние библиотеки и приложения, как из nuget, так и подключаемые вручную. Решение должно быть запаковано в zip-архив с фиксированной структурой папок. Чтобы не ошибиться, рекомендуем воспользоваться утилитой Kontur.LogPacker.SubmitHelper из проекта с шаблоном.