Исключительные ситуации и локализация ошибок

SKY / WINGS / FIRST /
ERRORS2
child bonds:
В sky-приложениях, исключительные ситуации могут быть вызваны пятью способами:

1. throw new Error(..) - исключительная ситуация, вызванная действиями программиста. Такие исключительные ситуации регистрируются в CRASH логе. Их быть не должно и если они возникли, код скрипта должен быть исправлен. Если в течении длительного тестового периода код "throw new Error('err desc')" не срабатывает (или по другим причинам), то можно вместо текстового описания, использовать численное значение номера ошибки с кодом от 1 до 99, например "throw new Error(9)" Код ответа HTTP, если явно не переопределен, всегда равен 404.

2. фатальные ошибки PHP - тоже самое как и для пункта 1, но только описанием исключительной ситуация занимается ядро PHP а не программист.

3. throw new Stop(..) - исключительные ситуации никогда не регистрируются в CRASH логе. Вызов, если явно не определено, не изменяет предустановленный HTTP ответ сервера (обычно 200). Специальный случай: throw new Stop, вызов без параметров, ничего не дописывает в STDOUT.

4. throw new Exception(..) - исключительная ситуация, вызванная внешними по отношению к скрипту событиями. Такие ситуации могут возникать, например, при попытках взлома кода приложения. Они могут регистрироваться в CRASH логе на продакшн, а могут и не регистрироваться, в зависимости от настройки в админ разделе. Код ответа HTTP, если явно не переопределен, всегда равен 404. Для Log Error `throw new Exception(..)` никогда не считается ошибкой.

5. die (или синоним `exit`, когда $sky->tailed равно FALSE) - специальная исключительная ситуация типа "throw new Exception". Для явного "крышевания" кода приложения, следует использовать инструкцию PHP `die`. Использование `die` вместо `exit` явно указывает на код крышевания. В админ разделе можно настроить код ответа HTTP 404 или 403 для таких ситуаций. Для случая 403, описание будет "Denied hacking attempt", для 404 - "Page not found".

Исключительные ситуации могут быть вызваны, при возврате из специальных методов контроллеров (с префиксом a_) значения 404. Если в админ разделе указано "выполнять `Stop` для return 404", то будет выполняться throw new Stop(404), это более производительный вариант обработки. Но если указано "не выполнять `Stop` для return 404", то исключительная ситуация не произойдет, будет показана страница 404 и код ответа HTTP будет 404, но будут вычислены все переменные для визуализации Layout-части отображения. Если быстродействие не критично, резонно использовать второй вариант. С другой стороны, для максимальной маскировки от взломщиков, следует использовать настройки: "выполнять `Stop` для return 404" и "при сработке кода крышевания генерировать 404 а не 403", тогда ответ сервера, для любых ошибок 404 или срабатывания кода крышевания, всегда будет полностью идентичен.

При возникновении исключительных ситуаций, по умолчанию, код ответа HTTP равен 404 (кроме throw new Stop), а описание в тегах <h1> и <title> - "Page not found". Но код может явно задаваться во время определения исключительной ситуации. Если явно указан код ответа HTTP, также на страницу ответа, передается описание ошибки в тег <title> и <h1> (в том числе на продакшн), например: throw new Stop('403 You are banned'). Но если код ответа не задан, например, throw new Exception('Banned visitor'), в CRASH лог запишется сообщение "Banned visitor" и GET часть запроса от посетителя, а непосредственно ему в ответ уйдет 404 - Page not found.

Опция в админ-разделеОписание
Use Log CRASHОбщий "рубильник" Log CRASH. Если выключен, в лог, никогда ничего не запишется. Обычно опция должна быть активна. Но если требуется поднять производительность сервера, опцию можно отключить, это гарантированно исключит SQL запрос записи в Log CRASH.
Use Log ERRORЕсли активно - записывает фатальные и не фатальные ошибки PHP, в том числе на продакшн, когда $sky->debug равно FALSE (трассировка при этом не собирается). Выполнение `throw new Error(..)` равносильно фатальной ошибке PHP, а `throw new Exception(..)` не считается ошибкой
Use Stop on `return 404`Выполнять throw new Stop(404), когда из специальных методов контроллеров возвращается 404 значение
No Exceptions in Log CRASHНе писать в Log CRASH, если сработал код крышевания (с помощью `die`) или  throw new Exception(..). Можно оставить опцию неактивной, но если будет писаться слишком много попыток взлома, лог нужно очистить и активировать опцию.
Use 403 code for `die`Использовать код ответа HTTP 403 для кода крышевания, вместо 404.


В режиме отладки, вся информация (плюс полная трассировка) об исключительной ситуации видна посетителю, за исключением `throw new Stop`.

Иногда, например, при запросах на скачивание файлов, удобно прекратить выполнение скрипта не вызывая исключительной ситуации. В таких случаях используйте `exit` вместо `die` и присваивайте $sky->tailed = true; перед `exit` или же можно использовать `throw new Stop`.

Идеально отлаженное приложение должно иметь всегда пустой "Log Error" и "Log Crash". Если Log Crash не пустой, для root-профиля, общий фон админ раздела будет желтый вместо белого. А если Log Error не пустой, то "шапка" админ раздела будет красной для root-профиля. Если в Log Error появилась новая запись (не просмотрена ни разу никем), с помощью функционала CRON-layer, main/w2/schedule.php, легко организовать отсылку письма, по расписанию, на E-mail root-разработчика.

Код крышевания


Слово "крышевание" происходит от украинского слова "дах" (крыша), которое созвучно с аббревиатурой DAH от английского "Deny Attempts of Hacker". Взгляните на код:

001
002
003
004
005
006
007
<?php
function func($id) {
    is_numeric($id) or die;
    if (!$row $this->t_art->one($id))
        return 404;
    #...
}

В примере выше, $id статьи, вначале проверяется на численное значение, и если оно не численное, срабатывает код крышевания, скрипт прекращает выполнение. Этот код однозначно детектирует попытки взлома, если хакер пытается в запросе передать строковые данные, например одинарные кавычки для инъекций. Нет смысла обслуживать запросы хакеров, поэтому скрипт сразу останавливается. В следующей строке, если статья не найдена, то код возвращает 404. Во втором случае, статья могла существовать, но позже могла быть санкционировано удалена по определенному $id, это код валидации, но не код крышевания. Это просто код проверки на существование статьи. Для случая, если такой код используется в некой CRM, резонно не вызывать "Exception", а вычислить переменные layout, показать меню приложения, чтобы пользователю было удобно перейти со страницы 404 на другую. В Интернете результат выдачи в обоих случаях может быть одинаков, но следует их различать и привыкнуть программировать единообразно как для CRM так и для сайтов: для крышевания использовать `die` для кода валидации `return 404`.

Функция trace(..)


В ядре SKY Framework существует функция trace(), обращаясь к которой, можно осуществлять трассировку скрипта и показывать значения переменных. Функция также вызывается автоматически из некоторых других функций и методов классов. Например, из функции-обертки sql(). Так ошибка в запросе SQL будет автоматически обнаружена и показана как ошибка приложения, подобно ошибкам PHP уровня Notice или Warning.

Стандартный обработчик ошибок PHP заменен методом SKY::error(). Это позволяет показывать ошибки более удобным образом, показывать трассировку вызовов (используя функцию PHP debug_print_backtrace()), показывать значение контекстных переменных. В случае появления ошибки PHP, вызывается обработчик ошибок SKY::error(), который с свою очередь вызывает функцию trace() с пометкой "ошибка". В случае неверно составленного SQL запроса происходит тоже самое. А функция trace() уже реализует этот дополнительный вышеописанный функционал как центральный обработчик.

Если ошибок нет, функция trace(), просто собирает трассировочную информацию в $sky->tracing. Собранная трассировочная информация выводится в браузер внутри тега <div style="display:none"> и может быть визуализирована по требованию (см. PDAXT), или она может быть записана в ячейку памяти (см. MEMORY) с целью просмотра в будущем (X-tracing).

Не фатальные ошибки и трассировка


Если в процессе работы скрипта произошли ошибки PHP или кода coresky, вся SKY-трассировка автоматически показывается разработчику, с выделением красным цветом мест с ошибками, PHP-трассировкой вызовов в местах с ошибками и контекстными переменными.

В SKY Framework имеется специальная схема для упрощенного программирования запросов AJAX. При возникновении ошибок, в течении обработки таких запросов, имеется специальный механизм принужденной визуализации, также как и для обычных запросов. Если свойство $sky->was_error в конце выполнения скрипта истинно, то выдача данных в STDOUT преобразуется в JSON кодированный массив (вывод предварительно буферизируется с помощью ob_start()) с ключем "catch_error" и присоединенными отладочными данными. Стандартный обработчик AJAX запросов (функция ajax() на javascript), детектирует такой вывод данных, и показывает всплывающее окно с отладочной информацией.

В файле main/sky.php имеется функция check_other(), предназначенная для специальных проверок с целью дополнительного обнаружения ошибок. Ее запуск производится только когда обнаружены другие ошибки, поэтому она не снижает быстродействия на продакшн в нормальном режиме.

Трассировка и детектирование ошибок, должны быть всегда включены на рабочей станции разработчика (константа DEV равна true), и выключены в "боевом" режиме, на продакшн. Это необходимо для повышения производительности отладки на `dev` и в целях секретности, на продакшн. Константа DEV определяет тип инсталляции приложения, а константа DEBUG - режим отладки см. main/conf.php:

001
define('DEBUG', DEV ? 3 : 0);

Тем не менее, SKY Framework, позволяет делать отладку на production, когда константа DEBUG равна нулю (основной режим отладки выключен) в следующих случаях:

1. Можно включить (или выключить) коллекционирование ошибок и логирование их в ячейку memory.tmemo.ID=4, с целью ее просмотра, в дальнейшем, в административном разделе. При этом все вызовы функции trace(), когда параметр $show_error равен true, будут трактоваться как ошибки. Если $show_error не равен тождественно true, это не будет трактоваться как ошибка, сбор ошибок, при таких вызовах, не будет происходить и не будет собираться трассировка.

2. Можно включить трассировку единичного клика в ячейку X-tracing (memory.tmemo.ID=1). При активации такого режима в админ разделе, необходимо успеть сделать нужный клик. После первого же клика, в таком режиме, переменная $sky->s_trace_prod, в конце трассировки автоматически сбрасывается в ноль и трассировка для всех последующих кликов не будет происходить.

3. Для консольных запусков скриптов, в том числе с точкой входа START равно "cron", нет особых требований по безопасности, в плане того, что посетителя сайта увидят трассировку и это как то поможет взломать сайт. Редкие запуски cron скриптов (в единицу времени), по сравнению с потенциально возможно частыми для фронтальных скриптов, не будут ощутимо использовать ресурсы сервера из-за дополнительно работающего функционала по сбору трассировки. Поэтому в SKY Framework имеется возможность включить (или выключить) трассировку всех консольных запусков скриптов в ячейку памяти X-tracing.

В файле main/w2/schedule.php (CRON layer) имеется функция Schedule::sql(), которую можно использовать вместо sql(), при этом выполненные SQL запросы (плюс время начала выполнения и обычно результат выполнения) будут записываться в ячейку памяти memory.tmemo.ID=2. В админ разделе, имеется возможность просматривать содержимое "Cron Log", также как и "ERROR Log" и "X-tracing".
published ENERGY - 10 Oct 2015 07:56 GMT
last edit - 6 Nov 2018 10:55 GMT
 +  0  -  add comment