Ловим Енотисов при отладке на PHP: руководство для программистов

Если вы владелец сайта и думаете, что на нём нет ошибок, то вы ошибаетесь. Если вы программист и думаете, что некоторые ошибки можно не обрабатывать, то вы тоже ошибаетесь. В обоих случаях речь идёт о Енотисах (E_NOTICE). Далее вы узнаете, почему им нужно уделять внимание и как сделать удобный инструмент для хранения и обработки ошибок.

В PHP есть несколько уровней ошибок. Все знают что с ошибками уровня E_WARNING и, тем более, E_ERROR нужно бороться, исправлять их. А что вам известно о E_NOTICE? Чаще всего такие ошибки игнорируют, к ним, например, относится обращение к несуществующему элементу массива. Ну нет его, значит и не было, значит результат будет пустым и как-нибудь сам обработается, скажут некоторые.

На самом деле, за E_NOTICE может скрываться более серьёзная ошибка, которая только ожидает своего часа, а точнее полуночи субботы, когда все программисты уже спят и никто её сразу не заметит. Разве что ночной покупатель, увидев ошибку оформления заказа.

Хорошо, давайте обрабатывать E_NOTICE! E_NOTICE могут появляться периодически. Например, когда пользователь заполнил часть полей в форме заказа, а скрипт обратился к элементу, которого нет в $_REQUEST.

Может будем перехватывать все ошибки и отправлять на почту в техподдержку?  Отправлять на E-mail - хорошая идея, только если на одном хите будет сгенерировано не меньше сотни ошибок, почта будет завалена сообщениями, а почтовый сервер решит, что его DDoS-ят.

Поэтому, действовать будем осторожнее. Для начала отсортируем ошибки по категориям. Скорее всего получится так:

  1. Ошибки ядра CMS - теоретически могут появиться, трогать их не будем, ибо ядро;
  2. Чужие ошибки (если работает несколько программистов);
  3. Свои ошибки;
  4. Дубли ошибок - не совсем категория, но их тоже нужно обработать.

Где хранить ошибки, как вести их учёт? Если всё складывать в один лог-файл, то со временем он разрастается. Работать с ним не удобно, т.к. в результате получаем “портянку” из ошибок, часто с дублями - это хорошо знакомо программистам.

Создаём систему учёта

Поскольку на момент написания статьи по поисковому запросу “php manage errors” вы не найдёте ничего лучше, чем запись в файл или вывод в браузер, то напишем свою систему учёта.

Она должна:

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

Цель системы учёта - выделить из общего потока ошибок, те которые нужно обработать вручную. Далее по порядку. Напомню, что перехват ошибок в Битриксе можно настроить в файле /bitrix/.settings.php .

Настройка собственного обработчика в .settings.php Настройка собственного обработчика в .settings.php

Нужно указать свой класс-обработчик, который должен быть унаследован от ExceptionHandlerLog и реализовывать методы write(), initialize(), а также путь к файлу класса.

При появлении ошибки в обработчике нам доступна информация:

  • текст ошибки c названием файла и строкой;
  • трассировка.

Минимальный набор методов классе-обработчике Минимальный набор методов классе-обработчике

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

Формирования ID (хеша) ошибки Формирования ID (хеша) ошибки

О способах хранения ошибок

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



Преимущества

Недостатки

Применение

Файловая система

- запись файла-ошибки - это одна операция (fwrite(), например);

- для чтения ошибок можно использовать текстовый редактор;

- файлы можно пересылать, обмениваться, делать общими;

- нужно написать свой скрипт для вывода списка, управления;

Может использоваться для учёта всех типов ошибок.

База данных

- ошибок может быть много, с подробным описанием;

- поиск, добавление, удаление средствами СУБД;

- можно добавлять дополнительные поля (комментарии, статус и прочие).

- нужно написать свой скрипт для вывода списка, управления;

- есть риск появления ошибок, которые будут препятствовать записи в БД;

- сбор ошибок создаст дополнительную нагрузку на БД сайта;

Может использоваться для учёта всех типов ошибок.

E-mail

- сообщений может быть много;

- сообщения могут содержать подробный текст ошибок.

- при большом потоке сообщений об ошибках с ними становится сложно работать;

Оповещения об ошибках типа E_ERROR, E_WARNING (т.е. единичные случаи).

Мессенджеры (XMPP)

- мгновенная доставка;

- сообщений может быть много;

- нужна программа-клиент (Psi, например);

- сообщений может быть много, но лучше, если они будут короткими, т.к. большие логи неудобно читать.

Вывод фактов появления ошибок, без подробного описания.

SMS - сообщения

- быстрая доставка;

- не нужен интернет.

- нужно оплачивать;

- сообщения должны быть короткими.

Сообщения о критических ошибках.

Наш выбор — файловая система. Да, не так красиво, но зато наглядно, быстро и надёжно. Плюс к этому, файлами можно обмениваться и это решает задачу совместной работы.

Какие категории ошибок будут в нашей системе? Предлагаю такие:

  • "новая" - тут всё понятно;
  • "обработанная" - устранена программистом или не представляет вреда;
  • "системная" - ошибка ядра, её не исправляем;
  • "пропущена" - не требует обработки, т.к. создана намеренно, в тестовой среде.

Так как решили использовать файлы, то перечисленные категории - это папки. Изменение категории ошибки - это перемещение файла между папками.

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

Папки-категории ошибок и файлы ошибок в категории “Новые” Папки-категории ошибок и файлы ошибок в категории “Новые”

Пример содержимого файла ошибки Пример содержимого файла ошибки

Работа над ошибками

Перейдём к алгоритмам. Как будет работать сохранение одной ошибки:

  1. перехват в классе обработчике;
  2. создание хеша (ID);
  3. сохранение подробной информации в файл (в папку "новые").

Работать с массой файлов не удобно, поэтому напишем простой скрипт, который

  • выводит список категорий (выпадающий список);
  • выводит список ошибок выбранной категории (в виде ссылок на файлы);
  • позволяет переносить ошибку в выбранную категорию.

Тогда действия программиста:

  1. выбрать категорию "новые";
  2. кликнуть на ссылку на ошибку;
  3. обработать ошибку, переместить её в одну из категорий.

Список ошибок для обработки Список ошибок для обработки

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

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

Заключение

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

Список ошибок для обработки Список ошибок для обработки

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

Комментарии (2)

...
  • nook_ru
  • 21.02.2017 21:34:41
Для php есть monolog. Системы учета и аналитики уже придуманы: Sentry, Bugsnag и прочие
...
  • Плотников Артём
  • 22.02.2017 17:14:45
Спасибо, посмотрим!