diff --git a/better_statistics.admin.inc b/better_statistics.admin.inc
index bccc75c..f4c6f34 100644
--- a/better_statistics.admin.inc
+++ b/better_statistics.admin.inc
@@ -14,13 +14,15 @@ function _better_statistics_form_statistics_settings_form_alter(&$form, &$form_s
   $log_description = &$form['access']['statistics_enable_access_log']['#description'];
   $log_description .= ' ' . t('Also required by the Better Statistics module.');
 
-  // Create a fieldset for our settings.
+  $form['access']['#weight'] = -10;
+
+  // Create a fieldset for data collection settings.
   $form['better_statistics'] = array(
     '#type' => 'fieldset',
     '#collapsible' => FALSE,
-    '#title' => t('Better statistics settings'),
+    '#title' => t('Access log data'),
     '#description' => t('Select the data you would like to collect on each page request. Note that unchecking a field below will permanently delete all data collected for that field.'),
-    '#weight' => 0,
+    '#weight' => -8,
     '#tree' => TRUE,
     // Only show this fieldset if the accesslog is enabled.
     '#states' => array(
@@ -105,6 +107,75 @@ function _better_statistics_form_statistics_settings_form_alter(&$form, &$form_s
     );
   }
 
+  $form['access_log_restrictions'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Access log restrictions'),
+    '#description' => t('Define restrictions on when page requests are logged in the access log. As an example, you may want to disable logging in admin areas or, only log access for specific user roles.'),
+    '#weight' => -6,
+    // Only show this fieldset if the accesslog is enabled.
+    '#states' => array(
+      'visible' => array(
+        ':input[name="statistics_enable_access_log"]' => array('checked' => TRUE),
+      ),
+    ),
+  );
+  // Cache-based restrictions reference.
+  if (variable_get('cache', 0)) {
+    $form['access_log_restrictions']['caching'] = array(
+      '#type' => 'fieldset',
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+      '#title' => t('Cache'),
+    );
+    $form['access_log_restrictions']['caching']['log_cached_status'] = array(
+      '#markup' => t('Tracking of page requests served from cache is currently !log_cached_status. Visit !the_performance_configuration_page to change settings.', array(
+        '!log_cached_status' => '<strong>' . (variable_get('statistics_access_log_cached', TRUE) ? t('enabled') : t('disabled')) . '</strong>',
+        '!the_performance_configuration_page' => l(t('the performance configuration page'), 'admin/config/development/performance'),
+      )),
+    );
+  }
+  // Page-based restrictions.
+  $form['access_log_restrictions']['pages'] = array(
+    '#type' => 'fieldset',
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+    '#title' => t('Pages'),
+  );
+  $form['access_log_restrictions']['pages']['statistics_access_log_restrictions_page'] = array(
+    '#type' => 'radios',
+    '#options' => array(
+      0 => t('All pages except those listed'),
+      1 => t('Only the listed pages'),
+    ),
+    '#title' => t('Log requests on specific pages'),
+    '#default_value' => variable_get('statistics_access_log_restrictions_page', 0),
+  );
+  $form['access_log_restrictions']['pages']['statistics_access_log_restrictions_pages'] = array(
+    '#type' => 'textarea',
+    '#rows' => 2,
+    '#default_value' => variable_get('statistics_access_log_restrictions_pages', ''),
+    '#description' => t("Specify pages by using their paths. Enter one path per line. The '*' character is a wildcard. Example paths are %blog for the blog page and %blog-wildcard for every personal blog. %front is the front page.", array(
+      '%blog' => 'blog',
+      '%blog-wildcard' => 'blog/*',
+      '%front' => '<front>',
+    )),
+  );
+  // Role-based restrictions.
+  $form['access_log_restrictions']['roles'] = array(
+    '#type' => 'fieldset',
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+    '#title' => t('Roles'),
+    '#group' => 'restrictions_settings',
+  );
+  $form['access_log_restrictions']['roles']['statistics_access_log_restrictions_roles'] = array(
+    '#type' => 'checkboxes',
+    '#options' => user_roles(),
+    '#title' => t('Log requests for specific roles'),
+    '#default_value' => variable_get('statistics_access_log_restrictions_roles', array()),
+    '#description' => t('Log requests only for the selected role(s). If you select no roles, statistics will be collected for all users.'),
+  );
+
   // Add a submit handler to handle schema changes as a result of changes here.
   // Fire before the system settings; we don't want it to save variables.
   array_unshift($form['#submit'], 'better_statistics_settings_form_submit');
@@ -112,6 +183,25 @@ function _better_statistics_form_statistics_settings_form_alter(&$form, &$form_s
 
 
 /**
+ * Makes alterations to the core site performance settings configuration form.
+ */
+function _better_statistics_form_system_performance_settings_alter(&$form, &$form_state, $form_id) {
+  $form['caching']['statistics_access_log_restrictions_cache'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Log access statistics for pages served from cache'),
+    '#description' => t('Logging access statistics on cached page requests can negatively impact performance and scalability.'),
+    '#default_value' => variable_get('statistics_access_log_restrictions_cache', TRUE),
+    // Only show this field if caching is enabled.
+    '#states' => array(
+      'visible' => array(
+        ':input[name="cache"]' => array('checked' => TRUE),
+      ),
+    ),
+  );
+}
+
+
+/**
  * Submit handler for Better Statistics configuration settings.
  */
 function _better_statistics_settings_form_submit($form, &$form_state) {
diff --git a/better_statistics.api.php b/better_statistics.api.php
index 440a4c0..0b513b6 100644
--- a/better_statistics.api.php
+++ b/better_statistics.api.php
@@ -182,5 +182,22 @@ function hook_better_statistics_fields() {
 }
 
 /**
+ * Allows modules to react just before Better Statistics performs access log
+ * field data collection and just after all module.statistics.inc files have
+ * been loaded.
+ *
+ * A good use of this is to call better_statistics_request_is_loggable().
+ *
+ * Implementations of this hook should be placed in your module.statistics.inc.
+ */
+function hook_better_statistics_prelog() {
+  // Never record statistics for user 1.
+  global $user;
+  if ($user->uid == 1) {
+    better_statistics_request_is_loggable(FALSE);
+  }
+}
+
+/**
  * @}
  */
diff --git a/better_statistics.install b/better_statistics.install
index 5adb77f..a617eec 100644
--- a/better_statistics.install
+++ b/better_statistics.install
@@ -54,4 +54,8 @@ function better_statistics_uninstall() {
   }
 
   variable_del('better_statistics_fields');
+  variable_del('statistics_access_log_restrictions_cache');
+  variable_del('statistics_access_log_restrictions_page');
+  variable_del('statistics_access_log_restrictions_pages');
+  variable_del('statistics_access_log_restrictions_roles');
 }
diff --git a/better_statistics.module b/better_statistics.module
index 600e687..ac1b151 100644
--- a/better_statistics.module
+++ b/better_statistics.module
@@ -81,21 +81,30 @@ function better_statistics_exit() {
     drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION);
     include_once DRUPAL_ROOT . '/includes/unicode.inc';
 
-    // Get all declared fields and their computed values.
-    $fields = better_statistics_get_fields_data();
+    // Load all relevant module.statistics.inc files for hook invocations.
+    better_statistics_load_active_incs();
 
-    // Now that we have data, try to insert it.
-    try {
-      db_insert('accesslog')->fields($fields)->execute();
-    }
-    catch (Exception $e) {
-      // At least log core fields.
-      $defaults = better_statistics_get_default_fields();
-      $core_fields = array_intersect_key($fields, $defaults);
-      db_insert('accesslog')->fields($core_fields)->execute();
-
-      // Log the error.
-      watchdog('better statistics', 'There was an error collecting statistics data:<br /><br />@error', array('@error' => $e->getMessage()), WATCHDOG_ERROR);
+    // Allow all modules to react before logging begins.
+    module_invoke_all('better_statistics_prelog');
+
+    // Log the request if the request is loggable.
+    if (better_statistics_request_is_loggable()) {
+      // Get all declared fields and their computed values.
+      $fields = better_statistics_get_fields_data();
+
+      // Now that we have data, try to insert it.
+      try {
+        db_insert('accesslog')->fields($fields)->execute();
+      }
+      catch (Exception $e) {
+        // At least log core fields.
+        $defaults = better_statistics_get_default_fields();
+        $core_fields = array_intersect_key($fields, $defaults);
+        db_insert('accesslog')->fields($core_fields)->execute();
+
+        // Log the error.
+        watchdog('better statistics', 'There was an error collecting statistics data:<br /><br />@error', array('@error' => $e->getMessage()), WATCHDOG_ERROR);
+      }
     }
   }
 
@@ -143,6 +152,17 @@ function better_statistics_form_statistics_settings_form_alter(&$form, &$form_st
 
 
 /**
+ * Implements hook_form_FORM_ID_alter().
+ *
+ * @see _better_statistics_form_system_performance_settings_form_alter()
+ */
+function better_statistics_form_system_performance_settings_alter(&$form, &$form_state, $form_id) {
+  module_load_include('inc', 'better_statistics', 'better_statistics.admin');
+  _better_statistics_form_system_performance_settings_alter($form, $form_state, $form_id);
+}
+
+
+/**
  * Submit handler for the Better Statistics configuration form.
  *
  * @see _better_statistics_settings_form_submit()
@@ -197,22 +217,14 @@ function better_statistics_get_default_fields() {
  * Returns data for all valid, declared fields in preparation for DB insertion.
  */
 function better_statistics_get_fields_data() {
-  // Include this module's API file because of how core fields are implemented.
-  require_once(dirname(__FILE__) . '/better_statistics.statistics.inc');
+  // Ensure all module.statistics.inc files are loaded.
+  better_statistics_load_active_incs();
 
   $fields = variable_get('better_statistics_fields', better_statistics_get_default_fields());
   $field_data = array();
 
   // Loop through all custom fields.
   foreach ($fields as $field => $data) {
-    // If there's an inc file and it hasn't been loaded yet, load it.
-    if (isset($data['_file']) && !isset($already[$data['_file']])) {
-      if (file_exists(DRUPAL_ROOT . '/' . $data['_file'])) {
-        require_once(DRUPAL_ROOT . '/' . $data['_file']);
-        $already[$data['_file']] = TRUE;
-      }
-    }
-
     // Only insert data into this field if there's a callback to get data.
     if (is_callable($data['callback'])) {
       $field_data[$field] = $data['callback']($field);
@@ -224,6 +236,50 @@ function better_statistics_get_fields_data() {
 
 
 /**
+ * Loads module.statistics.inc files for all active fields.
+ */
+function better_statistics_load_active_incs() {
+  // Prevent this function from loading it multiple times.
+  static $loaded;
+
+  if (empty($loaded)) {
+    $loaded = TRUE;
+
+    // Include this module's API file because of how core fields are implemented.
+    require_once(dirname(__FILE__) . '/better_statistics.statistics.inc');
+
+    $fields = variable_get('better_statistics_fields', better_statistics_get_default_fields());
+
+    // Loop through each declaring field and require associated files.
+    foreach ($fields as $field => $data) {
+      // If there's an inc file and it hasn't been loaded yet, load it.
+      if (isset($data['_file'])) {
+        if (file_exists(DRUPAL_ROOT . '/' . $data['_file'])) {
+          require_once(DRUPAL_ROOT . '/' . $data['_file']);
+       }
+      }
+    }
+  }
+}
+
+
+/**
+ * Determines the loggability of the current request.
+ *
+ * @return
+ *   TRUE if the current page can be logged, FALSE otherwise.
+ */
+function better_statistics_request_is_loggable($allow_logging = NULL) {
+  $allow_logging_static = &drupal_static(__FUNCTION__, TRUE);
+
+  if (isset($allow_logging)) {
+    $allow_logging_static = $allow_logging;
+  }
+
+  return $allow_logging_static;
+}
+
+/**
  * Determines whether or not the current request is being served from cache.
  *
  * Note that you may need to use === to determine the cache status of the page,
diff --git a/better_statistics.statistics.inc b/better_statistics.statistics.inc
index f38a704..f93875b 100644
--- a/better_statistics.statistics.inc
+++ b/better_statistics.statistics.inc
@@ -119,3 +119,54 @@ function better_statistics_get_field_value($field) {
       return truncate_utf8($_SERVER['HTTP_USER_AGENT'], 255);
   }
 }
+
+
+/**
+ * Implements hook_better_statistics_prelog().
+ *
+ * Better Statistics provides inclusion/exclusion restrictions for collecting
+ * access log data based on request paths, user roles and cache status.
+ */
+function better_statistics_better_statistics_prelog() {
+  // Skip if page is served from cache and Better Statistics is set to
+  // exclude logging cached requests.
+  $cache_status = better_statistics_served_from_cache();
+  if ($cache_status && !variable_get('statistics_access_log_restrictions_cache', TRUE)) {
+    better_statistics_request_is_loggable(FALSE);
+    return;
+  }
+
+  // If there are page-based restrictions, check the page.
+  $restrict_pages = variable_get('statistics_access_log_restrictions_page', 0);
+  $pages = drupal_strtolower(variable_get('statistics_access_log_restrictions_pages', ''));
+  if ($restrict_pages || !empty($pages)) {
+    // Make sure drupal_match_path() is available.
+    require_once DRUPAL_ROOT . '/' . variable_get('path_inc', 'includes/path.inc');
+
+    // Convert the Drupal path to lowercase.
+    $path = drupal_strtolower(drupal_get_path_alias($_GET['q']));
+    // Compare the lowercase internal and lowercase path alias (if any).
+    $page_match = drupal_match_path($path, $pages);
+    if ($path != $_GET['q']) {
+      $page_match = $page_match || drupal_match_path($_GET['q'], $pages);
+    }
+
+    if ($page_match xor $restrict_pages) {
+      better_statistics_request_is_loggable(FALSE);
+      return;
+    }
+  }
+
+  // If role restrictions are specified, check the array.
+  $roles = variable_get('statistics_access_log_restrictions_roles', array());
+  $restrictions_count = array_count_values($roles);
+  if (isset($restrictions_count[0]) && $restrictions_count[0] < count($roles)) {
+    // Skip if user is not part of an included role.
+    global $user;
+    $roles_check = array_intersect($roles, array_keys($user->roles));
+    if (empty($roles_check)) {
+      better_statistics_request_is_loggable(FALSE);
+      return;
+    }
+  }
+}
diff --git a/better_statistics.test b/better_statistics.test
index 3964433..a0dbecd 100644
--- a/better_statistics.test
+++ b/better_statistics.test
@@ -12,6 +12,7 @@
 class BetterStatisticsTest extends DrupalWebTestCase {
 
   protected $stats_admin = 'admin/config/system/statistics';
+  protected $perf_admin = 'admin/config/development/performance';
 
   public static function getInfo() {
     return array(
@@ -39,7 +40,7 @@ class BetterStatisticsTest extends DrupalWebTestCase {
   }
 
   /**
-   * Test basic functionality of the module.
+   * Test admin configuration functionality of the module.
    */
   public function testConfigurationChanges() {
     // Create a user and log it in.
@@ -128,5 +129,109 @@ class BetterStatisticsTest extends DrupalWebTestCase {
     $query = db_query('SELECT aid FROM {accesslog}');
     $rows = $query->rowCount();
     $this->assertTrue($rows == 3, t('Accesslog data being collected when page cache is enabled (cache hit).'));
+
+    // Create a user and log it in.
+    $this->admin_user = $this->drupalCreateUser(array(
+      'access administration pages',
+      'administer statistics',
+      'access content',
+      'access statistics',
+      'administer site configuration',  // to be able to access performance settings
+    ));
+    $this->drupalLogin($this->admin_user);
+
+    // Disable logging of cached page requests.
+    $edit = array(
+      'statistics_access_log_restrictions_cache' => FALSE,
+    );
+    $this->drupalPost($this->perf_admin, $edit, t('Save configuration'));
+
+    // Check page access is not logged.
+    $this->drupalLogout();
+    db_truncate('accesslog')->execute();
+    // First get will be a MISS.
+    $this->drupalGet('node');
+    // Second get will be a HIT.
+    $this->drupalGet('node');
+    $query = db_query('SELECT aid FROM {accesslog}');
+    $rows = $query->rowCount();
+    // We expect the MISS to be logged, the HIT not.
+    $this->assertTrue($rows == 1, t('Accesslog data not being collected when page cache is enabled, and logging of cached pages is disabled.'));
+
+    // Re-enable logging of cached page requests.
+    $this->drupalLogin($this->admin_user);
+    $edit = array(
+      'statistics_access_log_restrictions_cache' => TRUE,
+    );
+    $this->drupalPost($this->perf_admin, $edit, t('Save configuration'));
+
+    // Set statistics to only log anonymous users.
+    $edit = array(
+      'statistics_access_log_restrictions_roles[1]' => 1,
+    );
+    $this->drupalPost($this->stats_admin, $edit, t('Save configuration'));
+
+    // Check page access is not logged.
+    db_truncate('accesslog')->execute();
+    $this->drupalGet('node');
+    $query = db_query('SELECT aid FROM {accesslog}');
+    $rows = $query->rowCount();
+    $this->assertTrue($rows == 0, t('Accesslog data not being collected when logging is only enabled for anonymous users.'));
+
+    // Log out and check page access is logged.
+    $this->drupalLogout();
+    db_truncate('accesslog')->execute();
+    $this->drupalGet('node');
+    $query = db_query('SELECT aid FROM {accesslog}');
+    $rows = $query->rowCount();
+    $this->assertTrue($rows == 1, t('Accesslog data being collected when logging is only enabled for anonymous users.'));
+    $this->drupalLogin($this->admin_user);
+
+    // Re-enable logging of all roles.
+    $edit = array(
+      'statistics_access_log_restrictions_roles[1]' => FALSE,
+    );
+    $this->drupalPost($this->stats_admin, $edit, t('Save configuration'));
+
+    // Disable logging of admin pages.
+    $edit = array(
+      'statistics_access_log_restrictions_pages' => 'admin/*',
+    );
+    $this->drupalPost($this->stats_admin, $edit, t('Save configuration'));
+
+    // Check admin page access is not logged.
+    db_truncate('accesslog')->execute();
+    $this->drupalGet('admin/config'); // for some reason, this logs an access to 'node'
+    db_truncate('accesslog')->execute();
+    $this->drupalGet('admin/config');
+    $query = db_query('SELECT aid FROM {accesslog}');
+    $rows = $query->rowCount();
+    $this->assertTrue($rows == 0, t('Accesslog data not being collected on defined exclusion.'));
+
+    // Check normal page access is logged.
+    db_truncate('accesslog')->execute();
+    $this->drupalGet('node');
+    $query = db_query('SELECT aid FROM {accesslog}');
+    $rows = $query->rowCount();
+    $this->assertTrue($rows == 1, t('Accesslog data being collected when exclusion is defined, but a non-excluded page is loaded.'));
+
+    // Enable logging of only admin pages.
+    $edit = array(
+      'statistics_access_log_restrictions_page' => 1,
+    );
+    $this->drupalPost($this->stats_admin, $edit, t('Save configuration'));
+
+    // Check normal page access is not logged.
+    db_truncate('accesslog')->execute();
+    $this->drupalGet('node');
+    $query = db_query('SELECT aid FROM {accesslog}');
+    $rows = $query->rowCount();
+    $this->assertTrue($rows == 0, t('Accesslog data not being collected when inclusion is defined, but a non-included page is loaded.'));
+
+    // Check admin page access is logged.
+    $this->drupalGet('admin/config');
+    $query = db_query('SELECT aid FROM {accesslog}');
+    $rows = $query->rowCount();
+    $this->assertTrue($rows == 1, t('Accesslog data being collected on defined inclusion.'));
   }
 }
