log-my-errors (LME) — небольшой проект @jsmarkus 2013 года для просмотра PHP-ошибок в браузере. Здесь разобран путь сообщения: PHP перехватывает событие, Node.js принимает его, браузер показывает строку и stack trace. Это пример устройства отладочного инструмента, а не рекомендация подключать старый пакет к рабочему PHP-сервису.
Первоначальная задача возникла при разборе старого PHP-проекта с неудобным журналом ошибок. Автор хотел быстро видеть сообщения и значения переменных, не переключаясь между файлами журнала. Такой просмотр дополняет debugger, но не заменяет пошаговую отладку.
Xdebug позволяет останавливаться в нужном месте программы и исследовать состояние. Консоль LME решает более узкую задачу: показывает переданные ей сообщения. Это разные инструменты, и наличие красивой строки в браузере не доказывает, что обработаны все классы ошибок PHP.
Возможности перехвата исключений, предупреждений и фатальных ошибок зависят от обработчиков и версии PHP. Не обещайте, что произвольный вставленный snippet перехватит абсолютно любую ошибку. Проверяйте каждый нужный тип события отдельным тестом.
Так появилась утилита log-my-errors (сокращенно LME, npm: log-my-errors, github: jsmarkus/log-my-errors).
Установка и границы эксперимента
Исходный проект: jsmarkus/log-my-errors. Перед запуском старой версии прочитайте её исходники, зависимости, состояние поддержки и PHP-snippet. Установка через sudo npm -g для этого не требуется и здесь не предлагается.
Если нужно воспроизвести историческое поведение, используйте отдельную одноразовую VM или контейнерную лабораторию без рабочих данных и доступа к рабочей сети. Пакет устанавливают локально в этой лаборатории, фиксируя выбранную версию и lockfile; актуальная совместимость со свежими Node.js/PHP в этой статье не заявляется.
До передачи сообщений убедитесь, что слушатель привязан только к 127.0.0.1/::1. Открытие в браузере адреса 127.0.0.1 само по себе этого не доказывает: процесс может одновременно слушать все интерфейсы. На Linux адрес слушателя показывает ss -ltnp, на macOS — lsof -nP -iTCP:7001 -sTCP:LISTEN. Если виден wildcard-адрес, не начинайте передачу данных: сначала ограничьте bind в изученной копии кода и повторите проверку.
В исходной версии веб-интерфейс использовал локальный порт 7001. Это номер исторического примера, а не требование открыть порт на сервере. На изолированном loopback-экземпляре интерфейс выглядел так:

Кнопка Get code выдаёт PHP-код подключения. Сначала прочитайте его целиком: куда он отправляет данные, какие обработчики заменяет и какие побочные эффекты имеет. Не копируйте код автоматически в приложение.
Вставка кода и перехват ошибок
Подключайте изученный snippet только к отдельному учебному PHP-проекту. Endpoint должен оставаться на loopback той же лаборатории. Создайте синтетическую ошибку без паролей, cookies, токенов, персональных данных и фрагментов рабочих запросов.
Проверьте, что ожидаемое тестовое событие появилось ровно один раз. Отдельно проверьте поведение без запущенного приёмника: отладочная интеграция не должна менять ответ приложения или скрывать исходный журнал ошибок. Не отправляйте в LME ошибки production-системы: stack trace и значения переменных могут содержать секреты.
Вот, примерно, так:

В исходном интерфейсе строка раскрывалась и показывала stack trace. Проверяйте и такой вывод только на синтетических данных: пути файлов и аргументы вызовов тоже могут быть чувствительной информацией.

Логгирование
В исходном PHP-snippet есть LME::log($something) для передачи значения в интерфейс. Передавайте короткое тестовое значение, например строку demo; не отправляйте целиком $_SERVER, $_COOKIE, объект сессии или конфигурацию. В отличие от локального console.log, здесь данные проходят через отдельный процесс.

Вот пока и всё, что умеет log-my-errors.
Технологии
В проекте использованы Node.js, Socket.IO и Knockout.js. PHP-код передаёт сообщение приёмнику, приёмник уведомляет браузер, интерфейс отображает событие. Эта цепочка объясняет, почему адрес слушателя и состав данных нужно проверять до интеграции.
В общем
Завершая опыт, удалите snippet из учебного проекта и остановите приёмник. Для текущей рабочей отладки используйте поддерживаемый инструментарий и официальную документацию Xdebug. Исторический LME полезен прежде всего как небольшой пример разделения сборщика событий, канала доставки и браузерного представления.