protected function extract(Account $account, Profile $profile, $tableName, $dateFrom, $dateTo)
 {
     $config = $account->getConfiguration();
     $cfg = $config[$tableName];
     $filters = isset($cfg['filters'][0]) ? $cfg['filters'][0] : null;
     $segment = isset($cfg['segment']) ? $cfg['segment'] : null;
     $resultSet = $this->gaApi->getData($profile->getGoogleId(), $cfg['dimensions'], $cfg['metrics'], $filters, $segment, $dateFrom, $dateTo);
     $this->logger->info("Extracting ...", ['dimensions' => $cfg['dimensions'], 'metrics' => $cfg['metrics'], 'dateFrom' => $dateFrom, 'dateTo' => $dateTo, 'results' => count($resultSet)]);
     if (empty($resultSet)) {
         $this->logger->warning("Query returned empty result", ['account' => $account->getAccountName(), 'profile' => $profile->getName(), 'outputTable' => $tableName]);
         return;
     }
     $csv = $this->getOutputCsv($tableName, $profile);
     $this->getDataManager()->saveToCsv($resultSet, $profile, $csv);
     // Paging
     $params = $this->gaApi->getDataParameters();
     if ($params['totalResults'] > $params['itemsPerPage']) {
         $pages = ceil($params['totalResults'] / $params['itemsPerPage']);
         for ($i = 1; $i < $pages; $i++) {
             $start = $i * $params['itemsPerPage'] + 1;
             $resultSet = $this->gaApi->getData($profile->getGoogleId(), $cfg['dimensions'], $cfg['metrics'], $filters, $segment, $dateFrom, $dateTo, 'ga:date', $start, $params['itemsPerPage']);
             $this->getDataManager()->saveToCsv($resultSet, $profile, $csv, true);
         }
     }
     $this->getDataManager()->uploadCsv($csv->getPathname(), $this->getOutputTable($account, $tableName), true);
 }