diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc
index 58958249889b52d0fcf429e4ccc2dd93f400bc4d..590f1ba35ce60ceb09fa5a188b6fe688085f0737 100644
--- a/includes/bootstrap.inc
+++ b/includes/bootstrap.inc
@@ -1097,15 +1097,17 @@ function request_uri() {
  * @param $type
  *   The category to which this message belongs.
  * @param $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!
+ *   The message to store in the log. Keep $message translatable
+ *   by not concatenating dynamic values into it! Variables in the
+ *   message should be added by using placeholder strings alongside
+ *   the variables argument to declare the value of the placeholders.
+ *   See t() for documentation on how $message and $variables interact.
  * @param $variables
  *   Array of variables to replace in the message on display or
  *   NULL if message is already translated or not possible to
  *   translate.
  * @param $severity
- *   The severity of the message, as per RFC 3164
+ *   The severity of the message, as per RFC 3164.
  * @param $link
  *   A link to associate with the message.
  *
diff --git a/includes/install.inc b/includes/install.inc
index 2af751c5bd08e2ba37ee9cebf2a1ab12347f58b7..b3358f28505e0644faf2dd06eec2fa422fb238c8 100644
--- a/includes/install.inc
+++ b/includes/install.inc
@@ -610,6 +610,7 @@ function drupal_uninstall_modules($module_list = array()) {
     // Uninstall the module.
     module_load_install($module);
     module_invoke($module, 'uninstall');
+    watchdog('system', '%module module uninstalled.', array('%module' => $module), WATCHDOG_INFO);
 
     // Now remove the menu links for all paths declared by this module.
     if (!empty($paths)) {
diff --git a/includes/module.inc b/includes/module.inc
index dbe51279bec67d39ec3e36f3a124fc43f6ea3e62..2e00088ebd099743ba5daddb67700bfbf506d078 100644
--- a/includes/module.inc
+++ b/includes/module.inc
@@ -258,6 +258,7 @@ function module_enable($module_list) {
         ->execute();
       drupal_load('module', $module);
       $invoke_modules[] = $module;
+      watchdog('system', '%module module enabled.', array('%module' => $module), WATCHDOG_INFO);
     }
   }
 
@@ -309,6 +310,7 @@ function module_disable($module_list) {
         ->condition('name', $module)
         ->execute();
       $invoke_modules[] = $module;
+      watchdog('system', '%module module disabled.', array('%module' => $module), WATCHDOG_INFO);
     }
   }
 
diff --git a/modules/system/system.test b/modules/system/system.test
index 60c872df083858b1aeb894444e5ecc3ecde77f4d..1013901480ec71a18f124fcf4638497fba37cfc6 100644
--- a/modules/system/system.test
+++ b/modules/system/system.test
@@ -52,6 +52,40 @@ class ModuleTestCase extends DrupalWebTestCase {
       $this->assertEqual(module_exists($module), $enabled, t($message, array('@module' => $module)));
     }
   }
+
+  /**
+   * Verify a log entry was entered for a module's status change.
+   * Called in the same way of the expected original watchdog() execution.
+   *
+   * @param $type
+   *   The category to which this message belongs.
+   * @param $message
+   *   The message to store in the log. Keep $message translatable
+   *   by not concatenating dynamic values into it! Variables in the
+   *   message should be added by using placeholder strings alongside
+   *   the variables argument to declare the value of the placeholders.
+   *   See t() for documentation on how $message and $variables interact.
+   * @param $variables
+   *   Array of variables to replace in the message on display or
+   *   NULL if message is already translated or not possible to
+   *   translate.
+   * @param $severity
+   *   The severity of the message, as per RFC 3164.
+   * @param $link
+   *   A link to associate with the message.
+   */
+  function assertLogMessage($type, $message, $variables = array(), $severity = WATCHDOG_NOTICE, $link = '') {
+    $count = db_select('watchdog', 'w')
+      ->condition('type', $type)
+      ->condition('message', $message)
+      ->condition('variables', serialize($variables))
+      ->condition('severity', $severity)
+      ->condition('link', $link)
+      ->countQuery()
+      ->execute()
+      ->fetchField();
+    $this->assertTrue($count > 0, t('watchdog table contains @count rows for @message', array('@count' => $count, '@message' => $message)));
+  }
 }
 
 /**
@@ -87,6 +121,7 @@ class EnableDisableTestCase extends ModuleTestCase {
     $this->assertText(t('hook_modules_enabled fired for aggregator'), t('hook_modules_enabled fired.'));
     $this->assertModules(array('aggregator'), TRUE);
     $this->assertTableCount('aggregator', TRUE);
+    $this->assertLogMessage('system', "%module module enabled.", array('%module' => 'aggregator'), WATCHDOG_INFO);
 
     // Disable aggregator, check tables, uninstall aggregator, check tables.
     $edit = array();
@@ -98,6 +133,7 @@ class EnableDisableTestCase extends ModuleTestCase {
     $this->assertText(t('hook_modules_disabled fired for aggregator'), t('hook_modules_disabled fired.'));
     $this->assertModules(array('aggregator'), FALSE);
     $this->assertTableCount('aggregator', TRUE);
+    $this->assertLogMessage('system', "%module module disabled.", array('%module' => 'aggregator'), WATCHDOG_INFO);
 
     // Uninstall the module.
     $edit = array();
@@ -111,6 +147,7 @@ class EnableDisableTestCase extends ModuleTestCase {
     $this->assertText(t('hook_modules_uninstalled fired for aggregator'), t('hook_modules_uninstalled fired.'));
     $this->assertModules(array('aggregator'), FALSE);
     $this->assertTableCount('aggregator', FALSE);
+    $this->assertLogMessage('system', "%module module uninstalled.", array('%module' => 'aggregator'), WATCHDOG_INFO);
   }
 }