0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Известно, что программисты проводят много времени, отлаживая свои программы, пытаясь разобраться, почему они не работают - или работают неправильно. Когда говорят про отладку, обычно подразумевают либо отладочную печать, либо использование специальных программ - дебагеров. С их помощью отслеживается выполнение кода по шагам, во время которого видно, как меняется содержимое переменных. Эти способы хорошо работают в небольших программах, но в реальных приложениях быстро становятся неэффективными.</p>
1
<p>Известно, что программисты проводят много времени, отлаживая свои программы, пытаясь разобраться, почему они не работают - или работают неправильно. Когда говорят про отладку, обычно подразумевают либо отладочную печать, либо использование специальных программ - дебагеров. С их помощью отслеживается выполнение кода по шагам, во время которого видно, как меняется содержимое переменных. Эти способы хорошо работают в небольших программах, но в реальных приложениях быстро становятся неэффективными.</p>
2
<h2>Содержание</h2>
2
<h2>Содержание</h2>
3
<ul><li><a>Сложность реальных приложений</a></li>
3
<ul><li><a>Сложность реальных приложений</a></li>
4
<li><a>Логирование</a></li>
4
<li><a>Логирование</a></li>
5
<li><a>Уровни логирования</a></li>
5
<li><a>Уровни логирования</a></li>
6
<li><a>Ротация логов</a></li>
6
<li><a>Ротация логов</a></li>
7
</ul><h2>Сложность реальных приложений</h2>
7
</ul><h2>Сложность реальных приложений</h2>
8
<p>Возьмем для примера типичный сайт. Что он в себя включает?</p>
8
<p>Возьмем для примера типичный сайт. Что он в себя включает?</p>
9
<ul><li><a>DNS</a>. Система трансляции имени сайта в ip-адрес сервера.</li>
9
<ul><li><a>DNS</a>. Система трансляции имени сайта в ip-адрес сервера.</li>
10
<li>Веб-сервер. Программа, обслуживающая входящие запросы, перенаправляет их в код приложения и забирает от приложения данные для пользователей.</li>
10
<li>Веб-сервер. Программа, обслуживающая входящие запросы, перенаправляет их в код приложения и забирает от приложения данные для пользователей.</li>
11
<li>Физический сервер (или виртуальный) с его окружением. Включает в себя операционную систему, установленные и запущенные обслуживающие программы, например, мониторинг.</li>
11
<li>Физический сервер (или виртуальный) с его окружением. Включает в себя операционную систему, установленные и запущенные обслуживающие программы, например, мониторинг.</li>
12
<li>База данных. Внешнее хранилище, с которым связывается код приложения и обменивается информацией.</li>
12
<li>База данных. Внешнее хранилище, с которым связывается код приложения и обменивается информацией.</li>
13
<li>Само приложение. Помимо кода, который пишут программисты, приложение включает в себя сотни тысяч и миллионы строк кода сторонних библиотек. Кроме этого, код работает внутри фреймворка, у которого свои собственные правила обработки входящих запросов.</li>
13
<li>Само приложение. Помимо кода, который пишут программисты, приложение включает в себя сотни тысяч и миллионы строк кода сторонних библиотек. Кроме этого, код работает внутри фреймворка, у которого свои собственные правила обработки входящих запросов.</li>
14
<li>Фронтенд часть. Код, который выполняется в браузере пользователя. И системы сборки для разработки, например,<a>Webpack</a>.</li>
14
<li>Фронтенд часть. Код, который выполняется в браузере пользователя. И системы сборки для разработки, например,<a>Webpack</a>.</li>
15
</ul><p>И это только самый простой случай. Реальность же значительно сложнее: множество разноплановых серверов, системы кеширования (ускорения доступа), асинхронный код, очереди, внешние сервисы, облачные сервисы. Все это выглядит как многослойный пирог, внутри которого где-то работает написанный нами код. И этот код составляет лишь небольшую часть всего происходящего. Как в такой ситуации понять, на каком этапе был сбой, или все пошло не по плану? Для этого, как минимум, нужно определить, в каком слое произошла ошибка. Но даже это не самое сложное. Об ошибках в работающем приложении узнают не сразу, а уже потом, - когда ошибка случилась и, иногда, больше не воспроизводится.</p>
15
</ul><p>И это только самый простой случай. Реальность же значительно сложнее: множество разноплановых серверов, системы кеширования (ускорения доступа), асинхронный код, очереди, внешние сервисы, облачные сервисы. Все это выглядит как многослойный пирог, внутри которого где-то работает написанный нами код. И этот код составляет лишь небольшую часть всего происходящего. Как в такой ситуации понять, на каком этапе был сбой, или все пошло не по плану? Для этого, как минимум, нужно определить, в каком слое произошла ошибка. Но даже это не самое сложное. Об ошибках в работающем приложении узнают не сразу, а уже потом, - когда ошибка случилась и, иногда, больше не воспроизводится.</p>
16
<h2>Логирование</h2>
16
<h2>Логирование</h2>
17
<p>И для всего этого многообразия систем существует единое решение - логирование. В простейшем случае логирование сводится к файлу на диске, куда разные программы записывают (логируют) свои действия во время работы. Такой файл называют логом или журналом. Как правило, внутри лога одна строчка соответствует одному действию.</p>
17
<p>И для всего этого многообразия систем существует единое решение - логирование. В простейшем случае логирование сводится к файлу на диске, куда разные программы записывают (логируют) свои действия во время работы. Такой файл называют логом или журналом. Как правило, внутри лога одна строчка соответствует одному действию.</p>
18
<p>Выше небольшой кусок лога веб-сервера Хекслета. Из него видно ip-адрес, с которого выполнялся запрос на страницу и какие ресурсы загружались, метод HTTP, ответ бекенда (кода) и размер тела ответа в HTTP. Очень важно наличие даты. Благодаря ей всегда можно найти лог за конкретный период, например на то время, когда возникла ошибка. Для этого логи<a>грепают</a>:</p>
18
<p>Выше небольшой кусок лога веб-сервера Хекслета. Из него видно ip-адрес, с которого выполнялся запрос на страницу и какие ресурсы загружались, метод HTTP, ответ бекенда (кода) и размер тела ответа в HTTP. Очень важно наличие даты. Благодаря ей всегда можно найти лог за конкретный период, например на то время, когда возникла ошибка. Для этого логи<a>грепают</a>:</p>
19
<p>Когда программисты только начинают свой путь, они, часто не зная причину ошибки, опускают руки и говорят "я не знаю, что случилось, и что делать". Опытный же разработчик всегда первым делом говорит "а что в логах?". Анализировать логи - один из базовых навыков в разработке. В любой непонятной ситуации нужно смотреть логи. Логи пишут все программы без исключения, но делают это по-разному и в разные места. Чтобы точно узнать, куда и как, нужно идти в документацию конкретной программы и читать соответствующий раздел документации. Вот несколько примеров:</p>
19
<p>Когда программисты только начинают свой путь, они, часто не зная причину ошибки, опускают руки и говорят "я не знаю, что случилось, и что делать". Опытный же разработчик всегда первым делом говорит "а что в логах?". Анализировать логи - один из базовых навыков в разработке. В любой непонятной ситуации нужно смотреть логи. Логи пишут все программы без исключения, но делают это по-разному и в разные места. Чтобы точно узнать, куда и как, нужно идти в документацию конкретной программы и читать соответствующий раздел документации. Вот несколько примеров:</p>
20
<ul><li><a>Ruby On Rails (Ruby)</a></li>
20
<ul><li><a>Ruby On Rails (Ruby)</a></li>
21
<li><a>Django (Python)</a></li>
21
<li><a>Django (Python)</a></li>
22
<li><a>Laravel (PHP)</a></li>
22
<li><a>Laravel (PHP)</a></li>
23
<li><a>Spring Boot (Java)</a></li>
23
<li><a>Spring Boot (Java)</a></li>
24
<li><a>Fastify (Node.js)</a></li>
24
<li><a>Fastify (Node.js)</a></li>
25
</ul><p>Многие программы логируют прямо в консоль, например Webpack показывает процесс и результаты сборки:</p>
25
</ul><p>Многие программы логируют прямо в консоль, например Webpack показывает процесс и результаты сборки:</p>
26
<p>Во фронтенде файлов нет, поэтому логируют либо прямо в консоль, либо к себе в бекенды (что сложно), либо в специализированные сервисы, такие как<a>LogRocket</a>.</p>
26
<p>Во фронтенде файлов нет, поэтому логируют либо прямо в консоль, либо к себе в бекенды (что сложно), либо в специализированные сервисы, такие как<a>LogRocket</a>.</p>
27
<h2>Уровни логирования</h2>
27
<h2>Уровни логирования</h2>
28
<p>Чем больше информации выводится в логах, тем лучше и проще отладка, но когда данных слишком много, то в них тяжело искать нужное. В особо сложных случаях логи могут генерироваться с огромной скоростью и в гигантских размерах. Работать в такой ситуации нелегко. Чтобы как-то сгладить ситуацию, системы логирования вводят разные уровни. Обычно это:</p>
28
<p>Чем больше информации выводится в логах, тем лучше и проще отладка, но когда данных слишком много, то в них тяжело искать нужное. В особо сложных случаях логи могут генерироваться с огромной скоростью и в гигантских размерах. Работать в такой ситуации нелегко. Чтобы как-то сгладить ситуацию, системы логирования вводят разные уровни. Обычно это:</p>
29
<ul><li>debug</li>
29
<ul><li>debug</li>
30
<li>info</li>
30
<li>info</li>
31
<li>warning</li>
31
<li>warning</li>
32
<li>error</li>
32
<li>error</li>
33
</ul><p>Поддержка уровней осуществляется двумя способами. Во-первых, внутри самой программы расставляют вызовы библиотеки логирования в соответствии с уровнями. Если произошла ошибка, то логируем как<em>error</em>, если это отладочная информация, которая не нужна в обычной ситуации, то уровень<em>debug</em>.</p>
33
</ul><p>Поддержка уровней осуществляется двумя способами. Во-первых, внутри самой программы расставляют вызовы библиотеки логирования в соответствии с уровнями. Если произошла ошибка, то логируем как<em>error</em>, если это отладочная информация, которая не нужна в обычной ситуации, то уровень<em>debug</em>.</p>
34
<p>Во-вторых, во время запуска программы указывается уровень логирования, необходимый в конкретной ситуации. По умолчанию используется уровень<em>info</em>, который используется для описания каких-то ключевых и важных вещей. При таком уровне будут выводиться и<em>warning</em>, и<em>error</em>. Если поставить уровень<em>error</em>, то будут выводиться только ошибки. А если<em>debug</em>, то мы получим лог, максимально наполненный данными. Обычно<em>debug</em>приводит к многократному росту выводимой информации.</p>
34
<p>Во-вторых, во время запуска программы указывается уровень логирования, необходимый в конкретной ситуации. По умолчанию используется уровень<em>info</em>, который используется для описания каких-то ключевых и важных вещей. При таком уровне будут выводиться и<em>warning</em>, и<em>error</em>. Если поставить уровень<em>error</em>, то будут выводиться только ошибки. А если<em>debug</em>, то мы получим лог, максимально наполненный данными. Обычно<em>debug</em>приводит к многократному росту выводимой информации.</p>
35
<p>Уровни логирования, обычно, выставляются через переменную окружения во время запуска программы. Например, так:</p>
35
<p>Уровни логирования, обычно, выставляются через переменную окружения во время запуска программы. Например, так:</p>
36
<p>Существует и другой подход, основанный не на уровнях, а на пространствах имен. Этот подход получил широкое распространение в JS-среде, и является там основным. Фактически, он построен вокруг одной единственной библиотеки<a>debug</a>для логирования, которой пронизаны практически все JavaScript-библиотеки как на фронтенде, так и на бекенде.</p>
36
<p>Существует и другой подход, основанный не на уровнях, а на пространствах имен. Этот подход получил широкое распространение в JS-среде, и является там основным. Фактически, он построен вокруг одной единственной библиотеки<a>debug</a>для логирования, которой пронизаны практически все JavaScript-библиотеки как на фронтенде, так и на бекенде.</p>
37
<p>Принцип работы здесь такой. Под нужную ситуацию создается специализированная функция логирования с указанием пространства имен, которая затем используется для всех событий одного процесса. В итоге библиотека позволяет легко отфильтровать только нужные записи, соответствующие нужному пространству.</p>
37
<p>Принцип работы здесь такой. Под нужную ситуацию создается специализированная функция логирования с указанием пространства имен, которая затем используется для всех событий одного процесса. В итоге библиотека позволяет легко отфильтровать только нужные записи, соответствующие нужному пространству.</p>
38
<p>Запуск с нужным пространством:</p>
38
<p>Запуск с нужным пространством:</p>
39
<h2>Ротация логов</h2>
39
<h2>Ротация логов</h2>
40
<p>Со временем количество логов становится большим, и с ними нужно что-то делать. Для этого используется ротация логов. Иногда за это отвечает сама программа, но чаще - внешнее приложение, задачей которого является чистка. Эта программа по необходимости разбивает логи на более мелкие файлы, сжимает, перемещает и, если нужно, удаляет. Подобная система встроена в любую операционную систему для работы с логами самой системы и внешних программ, которые могут встраиваться в нее.</p>
40
<p>Со временем количество логов становится большим, и с ними нужно что-то делать. Для этого используется ротация логов. Иногда за это отвечает сама программа, но чаще - внешнее приложение, задачей которого является чистка. Эта программа по необходимости разбивает логи на более мелкие файлы, сжимает, перемещает и, если нужно, удаляет. Подобная система встроена в любую операционную систему для работы с логами самой системы и внешних программ, которые могут встраиваться в нее.</p>
41
<p>С веб-сайтами все еще сложнее. Даже на небольших проектах используется несколько серверов, на каждом из которых свои логи. А в крупных проектах тысячи серверов. Для управления такими системами созданы специализированные программы, которые следят за логами на всех машинах, скачивают их, складывают в заточенные под логи базы данных и предоставляют удобный способ поиска по ним.</p>
41
<p>С веб-сайтами все еще сложнее. Даже на небольших проектах используется несколько серверов, на каждом из которых свои логи. А в крупных проектах тысячи серверов. Для управления такими системами созданы специализированные программы, которые следят за логами на всех машинах, скачивают их, складывают в заточенные под логи базы данных и предоставляют удобный способ поиска по ним.</p>
42
<p>Здесь тоже есть несколько путей. Можно воспользоваться готовыми решениями, такими как<a>DataDog Logging</a>, либо устанавливать и настраивать все самостоятельно через, например,<a>ELK Stack</a></p>
42
<p>Здесь тоже есть несколько путей. Можно воспользоваться готовыми решениями, такими как<a>DataDog Logging</a>, либо устанавливать и настраивать все самостоятельно через, например,<a>ELK Stack</a></p>