Once Drupal bootstraps, it stops sending errors to PHP’s error log — which could be the web server error log, syslog or stderr on the command line. Error Log module adds the PHP error log as a Drupal logger implementation, so errors will once again appear in the same log or console that they appeared in before Drupal bootstrapped.
Because Drupal ≥8 does log some errors to PHP’s error log, redundant log messages may appear in some circumstances. Drush provides its own console logger; Error Log module is therefore not active in the Drush environment unless the PHP error_log configuration directive is set.
Similar modules:
Logging and Alerts has a similar errorlog (web server logging) module, but unfortunately it calls the theme() and t() functions, which should not be called by a logger, and does not fully clean up HTML-encoded exception messages. Monolog is a much more powerful solution for logging to the error log or elsewhere. The only advantage of Error Log module is bare bones simplicity. (This module can actually be used with Monolog by enabling the drupal.error_log handler.)
Credits:
Created and maintained by mfb – you can support development by contributing or sponsoring.
Supporting organizations:
Project information
Releases
8.x-1.12
released 22 January 2023
Works with Drupal: ^8 || ^9 || ^10
✓ Recommended by the project’s maintainer.
7.x-1.2
released 22 January 2023
Works with Drupal: 7.x
✓ Recommended by the project’s maintainer.
- View all releases
In Drupal 7, there is a function provided called watchdog, the function takes a number of different parameters.
watchdog($type,
$message,
$variables = array(),
$severity = WATCHDOG_NOTICE,
$link = NULL);
$type The category to which this message belongs. Can be any string, but the general practice is to use the name of the module that is calling the watchdog function.
$message The message to store in the log.
$variables Array of variables to replace in the message on display or NULL if message is already translated or not possible to translate.
$severity The severity of the message. Possible values are:
- WATCHDOG_EMERGENCY: Emergency, system is unusable.
- WATCHDOG_ALERT: Alert, action must be taken immediately.
- WATCHDOG_CRITICAL: Critical conditions.
- WATCHDOG_ERROR: Error conditions.
- WATCHDOG_WARNING: Warning conditions.
- WATCHDOG_NOTICE: (default) Normal but significant conditions.
- WATCHDOG_INFO: Informational messages.
- WATCHDOG_DEBUG: Debug-level messages.
$link A link to associate with the message.
As shown in the code below, the minimum you need is the type and message.
watchdog('my_module', 'my error message');
The below example adds in the contents of a variable and sets the severity to the WATCHDOG_NOTICE constant.
watchdog('mail',
'Email injection exploit attempted in email form subject: ' .
check_plain($form_state['values']['subject']),
WATCHDOG_NOTICE);
You can also output arrays and objects in a prettier/ more readable manner too, you just need to concatenate pre tags to your output.
watchdog('views_logging', '<pre>' . $output . '</pre>');
The below example is using placeholders that when rendered will be replaced with the value from an array that maps values to placeholders. Just to note, that the log entry is added to the database with the placeholders, it is only when the message is output into a UI or similar that the placeholders are rendered with the specified values.
watchdog('workflow',
'Attempt to go to nonexistent transition (from %old to %new)',
array('%old' => $old_sid, '%new' => $sid, WATCHDOG_ERROR));
Note: For related topics to this tutorial that you may need to understand, you may be interested in tutorials about using dependency injection, which is needed to get the logger service into your code. Understand the Service Container and Get a Service from the Container are good places to start with that. Additionally the Entity API Hooks tutorial uses logging as an example when working with entities.
Developers familiar with Drupal 7 will also be familiar with watchdog(), an API function that allows you to create a log message that appears on the Reports page in the Drupal administrative UI. Implementing D7’s hook_watchdog allows module developers to customize the destination of these log messages. In Drupal 8, both functions are replaced by a PSR-3-compatible logging interface (change notice).
In this tutorial, you’ll learn how to create the D8 equivalent of D7’s watchdog() function: creating a log message that appears on the Reports administrative page. In a future tutorial, we’ll cover how to create your own logger, and use it in your custom module. However, I’ve left you some hints and pointers at the end of this tutorial if you care to dive in before then.
Before and after
There is a straight-up D8 procedural equivalent of D7’s watchdog function, as we learn from the change notice:
Drupal 7 watchdog()
<?php
// Logs a notice
watchdog('my_module', $message, array());
// Logs an error
watchdog('my_module', $message, array(), WATCHDOG_ERROR);
?>
Drupal 8 logger class
<?php
// Logs a notice
Drupal::logger('my_module')->notice($message);
// Logs an error
Drupal::logger('my_module')->error($message);
?>
Learn from Examples
I downloaded the Examples for Developers module (version 8.x-1.x, but please consult the project page for the latest version) and looked for an example of this in action. I found a good one in the content_entity_example module within the Examples project.
After downloading Examples, open the project in your code editor or IDE of choice. (With Drupal 8’s object-oriented framework, I highly recommend using an IDE such as PhpStorm, simply because it makes navigating classes, methods, and their implementations so much easier. If you’re new to using an IDE, we have a nice set of PhpStorm IDE how-to videos from the creators, JetBrains, available on Drupalize.Me.)
Let’s take a look at the ContactDeleteForm class in examples/content_entity_example.
In your code editor, navigate to:
examples/content_entity_example/src/Form/ContactDeleteForm.php
If you have Examples downloaded to a Drupal 8 installation, that path is:
DRUPALROOT/modules/examples/content_entity_example/src/Form/ContactDeleteForm.php
In the submitform() method, we see the following:
public function submitForm(array &$form, FormStateInterface $form_state) {
$entity = $this->getEntity();
$entity->delete();
Drupal::logger('content_entity_example')->notice('@type: deleted %title.',
array(
'@type' => $this->entity->bundle(),
'%title' => $this->entity->label(),
));
$form_state->setRedirect('entity.content_entity_example_contact.collection');
}
Let’s break this down.
a. Drupal::
In this example, the submitForm method relies on the Drupal service container wrapper, a class which smoothes the transition from procedural to object-oriented code in the Drupal code base. The double colon means that we’re accessing a class from “elsewhere,” or outside of the class that it’s called from. It’s kind of like using an absolute path instead of relative one.
b. logger
A helper method that quickly creates a copy of the logger service.
In core/lib/Drupal.php, we find:
public static function logger($channel) {
return static::getContainer()->get('logger.factory')->get($channel);
}
So, from this, it looks like the logger method is way to kick-start the logger factory and get a copy of the logger to use in our code.
c. module name
The name of the module, in this case “content_entity_example.”
d. severity-level method
The name of the method in the Drupal::logger service (in this case “alert”), which will correspond to a severity level, i.e. debug, info, notice, warning, error, critical, alert, emergency. These can be also found in the PSRLogLoggerInterface in the file DRUPALROOT/vendor/psr/log/Psr/Log/LoggerInterface.php
e. log message
This can be a simple quoted PHP string, or a string that utilizes placeholders. In the latter case, pass in an associative array of specially formatted placeholder keys and values into the second parameter.
f. placeholders (array)
An array of placeholder keys and values. The key is the placeholder name with the appropriate prefix (see below for explanation), and the value is what should be used as a value. In this case, a method is called that supplies the value. Placeholders are provided so that values from context may be provided in the message. The logger will transform any placeholder messages to a safe format for output to HTML. For more information, see:
- public function LogMessageParserInterface::parseMessagePlaceholders
- public static function SafeMarkup::format
- protected static function FormattableMarkup::placeholderFormat
Placeholder types
@variable — Use this style of placeholder for most use-cases. Special characters in the text will be converted to HTML entities.
%variable — Use this style of placeholder to pass text through drupal_placeholder() which will result in HTML escaped text, then wrapped with <em> tags.
:variable — Use this style of placeholder when substituting the value of an href attribute. Values will be HTML escaped, and filtered for dangerous protocols.
How to view log messages as administrator
Log messages created with the Drupal::logger service can be viewed and filtered on the Reports page of the administrative UI. In the Administrative menu, go to Reports > Recent log messages. On this page is a list of recent log messages which you can filter by type and severity.
Why log messages?
Why would you want to use logging in your modules? You know how debug messages are really valuable during development? Well, when a site is in production and debug messages are no longer an option on a public site, log messages are a way to keep tabs on important things that are happening on your site—from notices about users signing in, to major errors that signal a problem that needs immediate attention. They can help you troubleshoot problems and find errors—both large and small—that need attention.
What should I be logging?
You can and should log anything that will help you keep tabs on what your users are doing, how the system is performing, and behind-the-scenes, automatic notifications, which can help you troubleshoot various errors. Things like:
- Actions performed by users
- Recoverable errors
- «Recurly notification processed»
As a developer, visit your Reports page often to learn about notices and recoverable errors that can let you know about places in your code that need attention. They may not be bringing down the system, but they are having some kind of impact and may point to one or more bugs.
Exercise: Implement your own logger
In Drupal 7, you could implement hook_watchdog in your module if you wanted to log messages to custom locations. In Drupal 8, hook_watchdog has been removed, and you now register your logger as a service in your module’s MODULENAME.services.yml, and then in your logger class, implement the PsrLogLoggerInterface and customize the logging destinations as you wish.
Several examples and variations of this can be found in core; for example, in contact, aggregator, and syslog core modules.
In a future tutorial, we’ll walk you through how to implement your own custom logger. For now, start using Drupal 8’s logger to create log messages in your fresh new Drupal 8 modules and keep an eye on that Reports page!
Happy logging!
Привычная функция watchdog, которую мы использовали в 6/7 версиях, к девятке пережила эволюцию до сервиса логирования.
Бывшее ранее:
|
watchdog(‘my_module’, $message, array(), WATCHDOG_ERROR); |
Сейчас выглядит так:
|
Drupal::logger(‘my_module’)—>error($message); |
Помимо того, что в 8/9 drupal мы переходим к использованию ООП подхода, логирование стало сервисом, который может расширятся в модулях.
Привычные константы уровня ошибки (severity) замены методами:
emergency($message, $context)— WATCHDOG_EMERGENCYalert($message, $context)— WATCHDOG_ALERTcritical($message, $context)— WATCHDOG_CRITICALerror($message, $context)— WATCHDOG_ERRORwarning($message, $context)— WATCHDOG_WARNINGnotice($message, $context)— WATCHDOG_NOTICEinfo($message, $context)— WATCHDOG_INFOdebug($message, $context)— WATCHDOG_DEBUG
Drupal 8/9
Написать комментарий
Данная запись опубликована в 08.10.2021 17:13 и размещена в drupal.
Вы можете перейти в конец страницы и оставить ваш комментарий.
Мало букафф? Читайте есчо !
Редирект после отправки формы в Drupal 8/9
Январь 22, 2022 г.
Для семерки можете посмотреть другую статью.
Обычно правят поведение существующих форм через hook_form_alter, добавляя туда еще один обработчик submit. Специальный метод setRedirectUrl объекта FormStateInterface позволяет настроить адрес перенаправления. …
Читать
Проверка, что поле пустое в twig
Январь 28, 2022 г.
При переходе к Drupal 8/9 на twig шаблоны, часто возникает вопрос, как проверить что поле пустое.
Наиболее точный ответ на мой взгляд помогает найти фильтр render, т.к. он позволяет получить результат рендера соответствующего поля, а не заниматься …
Читать
function _drupal_log_error
_drupal_log_error($error, $fatal = FALSE)
Logs a PHP error or exception and displays an error page in fatal cases.
Parameters
$error: An array with the following keys: %type, @message, %function, %file, %line, severity_level, and backtrace. All the parameters are plain-text, with the exception of @message, which needs to be an HTML string, and backtrace, which is a standard PHP backtrace.
bool $fatal: TRUE for:
- An exception is thrown and not caught by something else.
- A recoverable fatal error, which is a fatal error.
Non-recoverable fatal errors cannot be logged by Drupal.
File
- core/includes/errors.inc, line 128
- Functions for error handling.
Code
function _drupal_log_error($error, $fatal = FALSE) {
$is_installer = drupal_installation_attempted();
// Backtrace array is not a valid replacement value for t().
$backtrace = $error['backtrace'];
unset($error['backtrace']);
// When running inside the testing framework, we relay the errors
// to the tested site by the way of HTTP headers.
if (DRUPAL_TEST_IN_CHILD_SITE && !headers_sent() && (!defined('SIMPLETEST_COLLECT_ERRORS') || SIMPLETEST_COLLECT_ERRORS)) {
// $number does not use drupal_static as it should not be reset
// as it uniquely identifies each PHP error.
static $number = 0;
$assertion = array(
$error['@message'],
$error['%type'],
array(
'function' => $error['%function'],
'file' => $error['%file'],
'line' => $error['%line'],
),
);
// For non-fatal errors (e.g. PHP notices) _drupal_log_error can be called
// multiple times per request. In that case the response is typically
// generated outside of the error handler, e.g., in a controller. As a
// result it is not possible to use a Response object here but instead the
// headers need to be emitted directly.
header('X-Drupal-Assertion-' . $number . ': ' . rawurlencode(serialize($assertion)));
$number++;
}
$response = new Response();
// Only call the logger if there is a logger factory available. This can occur
// if there is an error while rebuilding the container or during the
// installer.
if (Drupal::hasService('logger.factory')) {
try {
Drupal::logger('php')->log($error['severity_level'], '%type: @message in %function (line %line of %file).', $error);
}
catch (Exception $e) {
// We can't log, for example because the database connection is not
// available. At least try to log to PHP error log.
error_log(strtr('Failed to log error: %type: @message in %function (line %line of %file).', $error));
}
}
// Log fatal errors, so developers can find and debug them.
if ($fatal) {
error_log(sprintf('%s: %s in %s on line %d', $error['%type'], $error['@message'], $error['%file'], $error['%line']));
}
if (PHP_SAPI === 'cli') {
if ($fatal) {
// When called from CLI, simply output a plain text message.
// Should not translate the string to avoid errors producing more errors.
$response->setContent(html_entity_decode(strip_tags(SafeMarkup::format('%type: @message in %function (line %line of %file).', $error))) . "n");
$response->send();
exit;
}
}
if (Drupal::hasRequest() && Drupal::request()->isXmlHttpRequest()) {
if ($fatal) {
if (error_displayable($error)) {
// When called from JavaScript, simply output the error message.
// Should not translate the string to avoid errors producing more errors.
$response->setContent(SafeMarkup::format('%type: @message in %function (line %line of %file).', $error));
$response->send();
}
exit;
}
}
else {
// Display the message if the current error reporting level allows this type
// of message to be displayed, and unconditionally in update.php.
$message = '';
$class = NULL;
if (error_displayable($error)) {
$class = 'error';
// If error type is 'User notice' then treat it as debug information
// instead of an error message.
// @see debug()
if ($error['%type'] == 'User notice') {
$error['%type'] = 'Debug';
$class = 'status';
}
// Attempt to reduce verbosity by removing DRUPAL_ROOT from the file path
// in the message. This does not happen for (false) security.
if (Drupal::hasService('app.root')) {
$root_length = strlen(Drupal::root());
if (substr($error['%file'], 0, $root_length) == Drupal::root()) {
$error['%file'] = substr($error['%file'], $root_length + 1);
}
}
// Check if verbose error reporting is on.
$error_level = _drupal_get_error_level();
if ($error_level != ERROR_REPORTING_DISPLAY_VERBOSE) {
// Without verbose logging, use a simple message.
// We call SafeMarkup::format() directly here, rather than use t() since
// we are in the middle of error handling, and we don't want t() to
// cause further errors.
$message = SafeMarkup::format('%type: @message in %function (line %line of %file).', $error);
}
else {
// With verbose logging, we will also include a backtrace.
// First trace is the error itself, already contained in the message.
// While the second trace is the error source and also contained in the
// message, the message doesn't contain argument values, so we output it
// once more in the backtrace.
array_shift($backtrace);
// Generate a backtrace containing only scalar argument values.
$error['@backtrace'] = Error::formatBacktrace($backtrace);
$message = SafeMarkup::format('%type: @message in %function (line %line of %file). <pre class="backtrace">@backtrace</pre>', $error);
}
}
if ($fatal) {
// We fallback to a maintenance page at this point, because the page generation
// itself can generate errors.
// Should not translate the string to avoid errors producing more errors.
$message = 'The website encountered an unexpected error. Please try again later.' . '<br />' . $message;
if ($is_installer) {
// install_display_output() prints the output and ends script execution.
$output = array(
'#title' => 'Error',
'#markup' => $message,
);
install_display_output($output, $GLOBALS['install_state'], $response->headers->all());
exit;
}
$response->setContent($message);
$response->setStatusCode(500, '500 Service unavailable (with message)');
$response->send();
// An exception must halt script execution.
exit;
}
if ($message) {
if (Drupal::hasService('session')) {
// Message display is dependent on sessions being available.
drupal_set_message($message, $class, TRUE);
}
else {
print $message;
}
}
}
}
_drupal_log_error($error, $fatal = FALSE)
Регистрирует ошибку или исключение PHP и отображает страницу ошибки в фатальных случаях.
Parameters
$ error : массив со следующими ключами:% type, @message,% function,% file,% line, severity_level и backtrace. Все параметры представляют собой обычный текст, за исключением @message, который должен быть строкой HTML, и обратной трассировки, которая является стандартной обратной трассировкой PHP.
bool $ fatal : TRUE для:
- Исключение бросается и не попадается на что-то другое.
- Восстанавливаемая фатальная ошибка.
Невосстановимые фатальные ошибки не могут быть зарегистрированы Drupal .
File
- core / includes / errors.inc , строка 128
- Функции для обработки ошибок.
Code
function _drupal_log_error($error, $fatal = FALSE) { $is_installer = drupal_installation_attempted(); $backtrace = $error['backtrace']; unset($error['backtrace']); if (DRUPAL_TEST_IN_CHILD_SITE && !headers_sent() && (!defined('SIMPLETEST_COLLECT_ERRORS') || SIMPLETEST_COLLECT_ERRORS)) { static $number = 0; $assertion = array( $error['@message'], $error['%type'], array( 'function' => $error['%function'], 'file' => $error['%file'], 'line' => $error['%line'], ), ); header('X-Drupal-Assertion-' . $number . ': ' . rawurlencode(serialize($assertion))); $number++; } $response = new Response(); if (Drupal::hasService('logger.factory')) { try { Drupal::logger('php')->log($error['severity_level'], '%type: @message in %function (line %line of %file).', $error); } catch (Exception $e) { error_log(strtr('Failed to log error: %type: @message in %function (line %line of %file).', $error)); } } if ($fatal) { error_log(sprintf('%s: %s in %s on line %d', $error['%type'], $error['@message'], $error['%file'], $error['%line'])); } if (PHP_SAPI === 'cli') { if ($fatal) { $response->setContent(html_entity_decode(strip_tags(SafeMarkup::format('%type: @message in %function (line %line of %file).', $error))) . "n"); $response->send(); exit; } } if (Drupal::hasRequest() && Drupal::request()->isXmlHttpRequest()) { if ($fatal) { if (error_displayable($error)) { $response->setContent(SafeMarkup::format('%type: @message in %function (line %line of %file).', $error)); $response->send(); } exit; } } else { $message = ''; $class = NULL; if (error_displayable($error)) { $class = 'error'; if ($error['%type'] == 'User notice') { $error['%type'] = 'Debug'; $class = 'status'; } if (Drupal::hasService('app.root')) { $root_length = strlen(Drupal::root()); if (substr($error['%file'], 0, $root_length) == Drupal::root()) { $error['%file'] = substr($error['%file'], $root_length + 1); } } $error_level = _drupal_get_error_level(); if ($error_level != ERROR_REPORTING_DISPLAY_VERBOSE) { $message = SafeMarkup::format('%type: @message in %function (line %line of %file).', $error); } else { array_shift($backtrace); $error['@backtrace'] = Error::formatBacktrace($backtrace); $message = SafeMarkup::format('%type: @message in %function (line %line of %file). <pre class="backtrace">@backtrace</pre>', $error); } } if ($fatal) { $message = 'The website encountered an unexpected error. Please try again later.' . '<br />' . $message; if ($is_installer) { $output = array( '#title' => 'Error', '#markup' => $message, ); install_display_output($output, $GLOBALS['install_state'], $response->headers->all()); exit; } $response->setContent($message); $response->setStatusCode(500, '500 Service unavailable (with message)'); $response->send(); exit; } if ($message) { if (Drupal::hasService('session')) { drupal_set_message($message, $class, TRUE); } else { print $message; } } } }
Лицензируется по Стандартной Общественной Лицензии GNU,версия 2 и более поздняя.
Drupal является зарегистрированной торговой маркой Dries Buytaert.
https://api.drupal.org/api/drupal/core!includes!errors.inc/function/_drupal_log_error/8.1.x
Отправка записей журнала watchdog в журнал ошибок PHP.
Модуль Error Log отправляет записи журнала watchdog в журнал ошибок PHP.
Друпал 7
После загрузки страницы, Друпал 7 перестаёт отправлять ошибки в журнал ошибок PHP — это может быть журнал ошибок веб-сервера, syslog или stderr в командной строке. Модуль Error Log добавляет журнал ошибок PHP как реализацию watchdog. Таким образом ошибки продолжают показываться в том же журнале или консоли, в которой они показывались до завершения загрузки. В Drush реализован свой собственный консольный журналист, поэтому Error Log не активируется в окружении Drush, если только конфигурация явно не указывает на его активацию.
Друпал 8
Друпал 8 отправляет в журнал ошибок PHP только определённые фатальные ошибки. Этот модуль добавляет журнал ошибок PHP как реализацию журналиста, поэтому дополнительные сообщения журнала отправляются в журнал ошибок. Так как ядро Друпала журналирует некоторые фатальные ошибки в журнале ошибок, в некоторых случаях могут появляться избыточные сообщения. В Drush реализован свой собственный консольный журналист, поэтому Error Log не активируется в окружении Drush, если только конфигурация явно не указывает на его активацию.
Fix Errors Whenever Possible
Although hiding error messages is important from a security perspective, errors and warnings mean that something isn’t working correctly, and that could likely have a negative effect on your site. It’s best to try to fix them to fix them if you can (especially if they are in your own code), or for third-party contrib modules, report them to the module or project owner.
PHP Message Types
PHP, which Drupal runs under, can generate three types of messages:
- Notices — Something to be aware of that you might want to do differently, but probably won’t keep your site from working.
- Warnings — More serious issues than Notices, but are not keeping your site from running.
- Errors — A serious issue that has caused the site code to stop running before reaching a normal completion.
In short, errors are problems that have to be fixed, because they are impeding use of your site. Warnings and notices ought to be fixed, but notices may be things that you have a reason for doing in an unusual way.
Drupal 7+ Message Settings
To change the way your Drupal 7 or 8 site shows PHP messages, go to the Configuration -> Development -> Logging and errors (admin/config/development/logging) administrative control page.
The recommended settings for a live, production site are:
- Error messages to display: None.
- Database log messages to keep: 100 (unless you need a longer audit trail)
- Note: Do not enable the core syslog module if you are using OIT hosting. According to the syslog module’s documentation, it is not appropriate for shared hosting. You should be able to find most useful debugging information by looking at the error logs, as described below.
Error Logs on OIT Web Hosting
If using OIT Web Hosting, you will find a record (or log) of errors the server is tracking in your Plesk control panel.
From the main panel, go into the Logs section and look for the log file called «error_log«. You can either view or download this file, which lists detailed error log messages.
Other forms of web hosting will have their own logging areas where you can look for error logs. Check with your server administrator to find out where the logs are on any non-OIT server that you might be using.
One thing to keep in mind is that server error logs will only contain messages from PHP. Any messages generated by Drupal itself will be found in the Drupal Error log, found in the administrative area of your site under Reports -> Recent log messages.
Sample Error Messages on Web Hosting
Here are some examples of error messages you might find in your hosting log:
[Mon Jun 15 03:01:53 2014] [warn] RSA server certificate CommonName (CN) `hosting.gatech.edu' does NOT match server name!? [Mon Jun 15 08:52:25 2014] [error] [client 130.207.000.00] File does not exist: /var/www/vhosts/mysite.gatech.edu/httpdocs/favicon.ico, referer: http://mysite.gatech.edu/node/77 [Mon Jun 15 09:03:20 2014] [warn] [client 130.207.000.00] mod_fcgid: stderr: PHP Warning: chdir(): open_basedir restriction in effect. File() is not within the allowed path(s): (/var/www/vhosts/mysite.gatech.edu/:/tmp/:/usr/share/pear:/var/cache/hg:/opt/atomic/atomic-php55/root/usr/share/pear) in /var/www/vhosts/mysite.gatech.edu/httpdocs/custom-file.php on line 88
- Printer-friendly version



