Я использую ведение журнала как способ сузить проблемы, которые не воспроизводятся в наших модульных тестах, не говоря уже о повторении тех же шагов, которые предоставляет пользователь: те редкие сбои, которые появляются только на некотором очень удаленном оборудовании (а иногда, хотя и очень редко даже из-за сбоя драйвера или сторонней библиотеки вне нашего контроля).
Я согласен с комментарием, что все это должно быть уловлено нашей процедурой тестирования, но трудно найти кодовую базу с миллионами LOC, которая требует очень низкоуровневого, критичного к производительности кода, чтобы когда-либо соответствовать этим требованиям. Я не работаю с критически важным программным обеспечением, но я работаю в графической индустрии, где нам часто приходится делать все: от реализации распределителей памяти до использования кода GPU и SIMD.
Даже с очень модульным, слабо связанным или даже полностью отделенным кодом, системные взаимодействия могут привести к очень сложным входам и выходам с поведением, изменяющимся на разных платформах, где иногда у нас есть тот случай изгоев, который ускользает от наших тестов. Модульные черные ящики могут быть очень простыми, но взаимодействие между ними может стать очень сложным и привести к случайному непредвиденному краю.
В качестве примера случая, когда логирование спасло мою задницу, однажды у меня был этот странный пользователь с прототипом машины Intel, которая зависала. Мы перечислили минимальные требования к машинам, которые должны поддерживать SSE 4, но этот конкретный компьютер удовлетворял этим минимальным требованиям и все еще не поддерживал расширения Streaming SIMD после SSE 3, несмотря на то, что он был 16-ядерным. Обнаружение этого стало возможным благодаря просмотру его журнала, в котором был точно указан номер строки, в которой использовались инструкции SSE 4. Никто из нас в нашей команде не мог воспроизвести проблему, не говоря уже об одном другом пользователе, который участвовал в проверке отчета. В идеале мы должны были бы написать код для более старых версий SIMD или, по крайней мере, выполнить некоторые ветвления и проверки, чтобы убедиться, что оборудование соответствует минимальным требованиям, но мы хотели сделать твердое предположение, основанное на минимальных требованиях к оборудованию, для простоты и экономии. Здесь, возможно, можно утверждать, что это были наши минимальные системные требования, которые имели «сбой».
Учитывая то, как я здесь использую логи, мы получаем довольно большие логи. Однако цель заключается не в удобочитаемости - обычно важна последняя строка журнала, отправляемая с отчетом, когда пользователь сталкивается с каким-то сбоем, которого никто из нас в команде (не говоря уже о нескольких других пользователях в мире) может воспроизводить.
Тем не менее, один прием, который я регулярно использую, чтобы избежать чрезмерного спама в журналах, состоит в том, что часто разумно предположить, что часть кода, которая выполняется один раз успешно, также будет делать это впоследствии (не жесткая гарантия, но часто разумное предположение). Поэтому я часто использую функцию log_once
для гранулярных функций, чтобы избежать затрат на регистрацию каждый раз, когда она вызывается.
Я не разбрасываю журналы повсюду (возможно, если бы у меня было время). Обычно я резервирую их больше всего для областей, которые кажутся наиболее опасными: код, вызывающий шейдеры GLSL, например (Поставщики графических процессоров здесь сильно различаются по возможностям и даже по тому, как они компилируют код), код с использованием встроенных функций SIMD, код очень низкого уровня, код, который неизбежно должен опираться на поведение, специфичное для ОС, предположения низкоуровневого кода, делающие предположения о представление POD (например: код, который принимает 8 бит на байт) - в тех случаях, когда мы также добавляем множество проверок утверждений и проверок работоспособности, а также пишем наибольшее количество модульных тестов. Как правило, этого достаточно, и ведение журнала спасло мою задницу много раз, и в противном случае я бы взял невоспроизводимый вопрос, и мне пришлось бы делать слепые удары по этой проблеме, требуя многих попыток отскакивания итераций для решения проблемы одного пользователя в мире, который может воспроизвести проблему.