How to use a terminate kernel event to log page access statistics? In Drupal 7 hook_exit is implemented in the Statistics module to gather statistics for page accesses. This change record suggest the equivalent in Drupal 8 is to listen for kernel.terminate events. Here's my code:

/mymodule/mymodule.services.yml

services:
  mymodule.page_exit:
    class: Drupal\mymodule\EventSubscriber\PageExit
    tags:
      - {name: event_subscriber}


/mymodule/src/Event/Subscriber/PageExit.php

namespace Drupal\mymodule\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;

class PageExit implements EventSubscriberInterface {

  /**
   * {@inheritdoc}
   */
  static function getSubscribedEvents() {
    $events[KernelEvents::TERMINATE][] = array('logAccess');
    return $events;
  }

  /**
   * Call this method whenever the KernelEvents::TERMINATE event is dispatched.
   */
  public function logAccess(PostResponseEvent $event) {

    // $access_info = $event-&gt;getRequest()

    \Drupal::database()-&gt;insert('mymodule_table')
      -&gt;fields(array(
        'hostname' =&gt; '?',
        'referrer_url' =&gt; '?',
        'timestamp' =&gt; REQUEST_TIME,
      ))
      -&gt;execute();
  }
}


Currently, for a single page request, the method logAccess gets called five times. I'm interested in logging the hostname and referrer url of my page visitor, just once.

In essence, I'm trying to port some of this this Drupal 7 code from statistics_exit in statistics.module:

drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION);

// For anonymous users unicode.inc will not have been loaded.
include_once DRUPAL_ROOT . '/includes/unicode.inc';
// Log this page access.
db_insert('accesslog')
  -&gt;fields(array(
    // 'title' =&gt; truncate_utf8(strip_tags(drupal_get_title()), 255),
    // 'path' =&gt; truncate_utf8($_GET['q'], 255),
    'url' =&gt; isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '',
    'hostname' =&gt; ip_address(),
    // 'uid' =&gt; $user-&gt;uid,
    // 'sid' =&gt; session_id(),
    // 'timer' =&gt; (int) timer_read('page'),
    'timestamp' =&gt; REQUEST_TIME,
  ))
  -&gt;execute();


Any ideas?
The comments you got are golden, my answer is along the lines of what @IvanJaros suggested, but follows a simpler approach. And take care to check the case of external caching (if any is in play).

The following should make your current approach work.

public function logAccess(PostResponseEvent $event) {

  $request_format = $event-&gt;getRequest()-&gt;getRequestFormat();

  if ($request_format === 'html') {
    // \Drupal::database()-&gt;
  }
  else {
    // Do other stuff.
  }
  ...


This snippet tries to detect requests with the html format (i.e. page requests) and will ignore other ones, like e.g. application/json.

Good luck!