function watchdog

You are here

7 bootstrap.inc watchdog($type, $message, $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL)
4.6 bootstrap.inc watchdog($type, $message, $severity = WATCHDOG_NOTICE, $link = NULL)
4.7 bootstrap.inc watchdog($type, $message, $severity = WATCHDOG_NOTICE, $link = NULL)
5 bootstrap.inc watchdog($type, $message, $severity = WATCHDOG_NOTICE, $link = NULL)
6 bootstrap.inc watchdog($type, $message, $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL)
8 bootstrap.inc watchdog($type, $message, array $variables = NULL, $severity = WATCHDOG_NOTICE, $link = NULL)

Log a system message.

Parameters

$type: The category to which this message belongs. Can be any string, but the general practice is to use the name of the module calling watchdog().

$message: The message to store in the log. See t() for documentation on how $message and $variables interact. Keep $message translatable by not concatenating dynamic values into it!

$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, as per RFC 3164. Possible values are WATCHDOG_ERROR, WATCHDOG_WARNING, etc.

$link: A link to associate with the message.

See also

watchdog_severity_levels()

92 calls to watchdog()
actions_do in includes/actions.inc
Perform a given list of actions by executing their callback functions.
actions_save in includes/actions.inc
Save an action and its associated user-supplied parameter values to the database.
actions_synchronize in includes/actions.inc
Synchronize actions that are provided by modules.
aggregator_form_category_submit in modules/aggregator/aggregator.admin.inc
Process aggregator_form_category form submissions.
aggregator_form_feed_submit in modules/aggregator/aggregator.admin.inc
Process aggregator_form_feed form submissions.

... See full list

4 string references to 'watchdog'
dblog_schema in modules/dblog/dblog.install
Implementation of hook_schema().
dblog_update_6000 in modules/dblog/dblog.install
Allow longer referrers.
system_update_6010 in modules/system/system.install
Add variable replacement for watchdog messages.
system_update_6019 in modules/system/system.install
Reconcile small differences in the previous, manually created mysql and pgsql schemas so they are the same and can be represented by a single schema structure.

File

includes/bootstrap.inc, line 950
Functions that need to be loaded on every Drupal request.

Code

function watchdog($type, $message, $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL) {
  global $user, $base_root;

  // Prepare the fields to be logged
  $log_message = array(
    'type' => $type,
    'message' => $message,
    'variables' => $variables,
    'severity' => $severity,
    'link' => $link,
    'user' => $user,
    'request_uri' => $base_root . request_uri(),
    'referer' => referer_uri(),
    'ip' => ip_address(),
    'timestamp' => time(),
  );

  // Call the logging hooks to log/process the message
  foreach (module_implements('watchdog') as $module) {
    module_invoke($module, 'watchdog', $log_message);
  }
}

Comments

For your own module development:

http://api.drupal.org/api/function/watchdog_severity_levels/6

<?php
function watchdog_severity_levels() {
  return array(
   
WATCHDOG_EMERG    => t('emergency'),
   
WATCHDOG_ALERT    => t('alert'),
   
WATCHDOG_CRITICAL => t('critical'),
   
WATCHDOG_ERROR    => t('error'),
   
WATCHDOG_WARNING  => t('warning'),
   
WATCHDOG_NOTICE   => t('notice'),
   
WATCHDOG_INFO     => t('info'),
   
WATCHDOG_DEBUG    => t('debug'),
  );
}
?>

This function is invaluable for debugging your own code.

In its simplest form, one might use the following code to insert new lines into the watchdog log.

<?php
watchdog
('error title', 'error message');
?>

An interesting quirk with this function is the variables array and the text in the log message. If you have a $variables['user'] element for example and then attempt to put the word 'user' anywhere in the message, you will encounter one of these 2 errors:

warning: preg_match() expects parameter 2 to be string, array given in /yourInstallDir/includes/bootstrap.inc on line 842.
OR
warning: preg_match() expects parameter 2 to be string, object given in /yourInstallDir/includes/bootstrap.inc on line 842.

This isnt a bug. It is intended and thus you have to fix your msg or variable to use a different case such as $variables['User'] and then you can use 'user' in the message or vice versa.

If this happens your code is broken. Those variables are the same as the ones that are passed on to t() and they should start with an exclamation mark (!), an at sign (@) or a percent sign (%). Translatable string replacement variables should never start with another character for safety reasons.

Note that $link should be an actual HTML link generated via l() or some such function not a link array as used in theme_links().

Thanks for the heads-up :) I was just wondering if I should l() it.

It would be really helpful if someone could post an example of how to use watchdog with some text that includes a variable, like "user XXX has just created a node titled XXX" or something..

<?php
  watchdog
('example', 'Example module is unable to find the file @filename.', array('@filename' => $filename), WATCHDOG_ERROR);
?>

In user.module:

watchdog('user', 'New user: %name (%email).', array('%name' => $name, '%email' => $mail), WATCHDOG_NOTICE, l(t('edit'), 'user/'. $account->uid .'/edit'));

An unfortunate limitation of watchdog if you want to use it in custom applications that don't use all of drupal (ie, you want to use drupal's database and session layers so you do drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION)) is that it requires "module_implements" which means the "module.inc" file must be loaded, which means that it can't be used before the drupal phase of DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE (I also think this means that it'll fail with aggressive caching).

Drupal 7 fixes this by adding function_exists('module_implements') but drupal 6 doesn't have it

"$type The category to which this message belongs. Can be any string, but the general practice is to use the name of the module calling watchdog()."

Calling watchdog with $type string greater than 16 chars will fail as it is stored in db as varchar(16).

Using module name as $type should therefore not be the recommended general practice as custom modules / sub-modules names may often exceed 16 chars...

The docs above state:

$variables Array of variables to replace in the message on display or NULL if message is already translated or not possible to translate.

If your message does not contain any tokens or string replacements, and you want to specify the severity, the quote above would indicate you should do this:

<?php
watchdog
('mymodule', $message, NULL, WATCHDOG_WARNING);
?>

However, doing so will result in this dread error message (bedeviling many different threads and irc chats):
preg_match() expects parameter 2 to be string, array given in docroot/includes/bootstrap.inc one line XXXX

So, don't follow the API docs. Use an empty array as your third parameter instead of NULL. ie, do this:

<?php
watchdog
('mymodule', $message, array(), WATCHDOG_WARNING);
?>

Of course, if the default WATCHDOG_NOTICE is good enough or you don't need to supply a link, just pass the first two parameters and don't worry about the rest as the default on the watchdog() end is to receive an array as the third param.

Suggestion: The watchdog() writers should specify with php that the third param is to be an array, like this
function watchdog($type, $message, array $variables=array(), .....

Log a system message. Do u think that's enough explanation for this function??

If I connect to another Database and use watchdog, it won't work as I'd expect.
For example:

db_set_active('db2');
user_save($user, array('name' => 'test',
'pass' => 'test',
'mail' => 'test@example.com',
'status' => 1)
); // create a new user in db2
watchdog("example module", $user->uid . " uid created", array(), WATCHDOG_INFO, null); // log the action in the default db
db_set_active('default');

It will create a new user into db2 as expected. The log, however, will be written in the default database.

Valid, but long, links may get truncated in watchdog() somewhere.

I tried using a perfectly legit link in watchdog() that was over 200 characters. The end of the URL and a bunch of markup got lopped off, leaving the log messages page all messed up and making my link invalid.

Disappointing.

Looking through the coding of the D7 version of this function vs. the D6 version, they basically wrap the entire function in an if switch:

  static $in_error_state = FALSE;

  // It is possible that the error handling will itself trigger an error. In that case, we could
  // end up in an infinite loop. To avoid that, we implement a simple static semaphore.
  if (!$in_error_state && function_exists('module_implements')) {
    /* SNIP */
    $in_error_state = FALSE;
  }

Does this mean that D6 is susceptible to an infinite loop if there's an error on watchdog? Are bug fixes like this not getting send back to D6?

While the error level (WATCHDOG_NOTICE, WATCHDOG_WARNING etc ) makes a difference in a console where you are reading the current system messages based in a logging level, it, unfortunately does NOT make a difference in the text generated to the file itself.

So, for example, the entry you find in /var/log/messages for this:
$ drush php-eval 'watchdog("MyModule", "My message !var %var2", array("!var" => "variable1", "%var2" => "variable2"), WATCHDOG_NOTICE,"http://mylink.com");'

Is this:

tail -1 /var/log/messages
Nov 28 18:15:49 myhostname drupal: http://default|1354144549|MyModule|127.0.0.1|http://default/index.php||0|http://mylink.com|My message variable1 variable2

If I "up" the message level to WATCHDOG_ERROR, the entry in the log file remains the same!
$ drush php-eval 'watchdog("MyModule", "My message !var %var2", array("!var" => "variable1", "%var2" => "variable2"), WATCHDOG_ERROR,"http://mylink.com");'

$ tail -1 /var/log/messages
Nov 28 18:15:49 myhostname drupal: http://default|1354144549|MyModule|127.0.0.1|http://default/index.php||0|http://mylink.com|My message variable1 variable2

In other words, the actual log entry in the log file has exactly the same info for an error as it does for a notice.

Thus, if you need to filter your logs only for warnings or errors, you can't, unless you use a console application or use the system service, which is not always possible with every host.

Suggestion: Put ERROR, WARNING, NOTICE at the start of your actual message text.
watchdog('MyModule', 'ERROR: My message !var %var2', array('!var' => 'variable1', '%var2' => 'variable2'), WATCHDOG_ERROR, 'http://mylink.com');

I want to know what the user enters into the view search ? watchdog can do it ?