campaigns * - newsletter * - partner * - campaign CPC * - referer * - search engine * - misc site * - same website * - url => multiple directories, page names * - multiple idsite * - multiple settings configurations * - action_name * - HTML title * * Objective: * Generate thousands of visits / actions per visitor with random data to test the performance * */ class Piwik_LogStats_Generator { private $currentget=array(); private $allget=array(); public $profiling; public $reinitProfilingAtEveryRequest = true; public $host = 'http://localhost'; protected $timestampToUse; public function __construct() { $_COOKIE = $_GET = $_REQUEST = $_POST = array(); // init GET and REQUEST to the empty array $this->setFakeRequest(); require_once "Piwik.php"; Piwik::createConfigObject('../config/config.ini.php'); // setup database Piwik::createDatabaseObject(); $this->profiling = true; Piwik_LogStats_Db::enableProfiling(); $this->timestampToUse = time(); } public function setTimestampToUse($timestamp) { $this->timestampToUse = $timestamp; } public function getTimestampToUse() { return $this->timestampToUse; } public function addParam( $name, $aValue) { if(is_array($aValue)) { $this->allget[$name] = array_merge( $aValue, (array)@$this->allget[$name]); } else { $this->allget[$name][] = $aValue; } } public function emptyAllLogTables() { $db = Zend_Registry::get('db'); $db->query('TRUNCATE TABLE '.Piwik::prefixTable('log_action')); $db->query('TRUNCATE TABLE '.Piwik::prefixTable('log_visit')); $db->query('TRUNCATE TABLE '.Piwik::prefixTable('log_link_visit_action')); } public function disableProfiler() { $this->profiling = false; Piwik_LogStats_Db::disableProfiling(); } public function end() { if($this->profiling) { function maxSumMsFirst($a,$b) { return $a['sum_time_ms'] < $b['sum_time_ms']; } $db = Zend_Registry::get('db'); $all = $db->fetchAll('SELECT *, sum_time_ms / count as avg_time_ms FROM '.Piwik::prefixTable('log_profiling').'' ); usort($all, 'maxSumMsFirst'); $str='

Query Profiling
----------------------
'; foreach($all as $infoQuery) { $query = $infoQuery['query']; $count = $infoQuery['count']; $sum_time_ms = $infoQuery['sum_time_ms']; $avg_time_ms = round($infoQuery['avg_time_ms'],1); $query = str_replace("\t", "", $query); $str .= "$query
$count times, $sum_time_ms ms total
$avg_time_ms ms average

"; } print($str); } } public function init() { if($this->profiling) { if($this->reinitProfilingAtEveryRequest) { $db = Zend_Registry::get('db'); $all = $db->query('TRUNCATE TABLE '.Piwik::prefixTable('log_profiling').'' ); } } // seed with microseconds function make_seed() { list($usec, $sec) = explode(' ', microtime()); return (float) $sec + ((float) $usec * 100000); } mt_srand(make_seed()); $common = array( 'res' => array('1289x800','1024x768','800x600','564x644','200x100','50x2000',), 'col' => array(24,32,16), 'idsite'=> 1, 'h' => range(0,23), 'm' => range(0,59), 's' => range(0,59), ); foreach($common as $label => $values) { $this->addParam($label,$values); } $downloadOrOutlink = array( Piwik_LogStats_Config::getInstance()->LogStats['download_url_var_name'], Piwik_LogStats_Config::getInstance()->LogStats['outlink_url_var_name'], ); $this->addParam('piwik_downloadOrOutlink', $downloadOrOutlink); $this->addParam('piwik_downloadOrOutlink', array_fill(0,8,'')); $campaigns = array( Piwik_LogStats_Config::getInstance()->LogStats['campaign_var_name'], Piwik_LogStats_Config::getInstance()->LogStats['newsletter_var_name'], Piwik_LogStats_Config::getInstance()->LogStats['partner_var_name'], ); $this->addParam('piwik_vars_campaign', $campaigns); $this->addParam('piwik_vars_campaign', array_fill(0,5,'')); $referers = array(); require_once "misc/generateVisitsData/Referers.php"; $this->addParam('urlref',$referers); $this->addParam('urlref',array_fill(0,2000,'')); $userAgent = $acceptLanguages = array(); require_once "misc/generateVisitsData/UserAgent.php"; require_once "misc/generateVisitsData/AcceptLanguage.php"; $this->userAgents=$userAgent; $this->acceptLanguage=$acceptLanguages; } public function generate( $nbVisits, $nbActionsMaxPerVisit ) { $nbActionsTotal = 0; for($i = 0; $i < $nbVisits; $i++) { // print("$i "); $nbActions = mt_rand(1, $nbActionsMaxPerVisit); Piwik_LogStats_Generator_Visit::setTimestampToUse($this->getTimestampToUse()); $this->generateNewVisit(); for($j = 1; $j <= $nbActions; $j++) { $this->generateActionVisit(); $this->saveVisit(); } $nbActionsTotal += $nbActions; } // print("
Generated $nbVisits visits."); // print("
Generated $nbActionsTotal actions."); return $nbActionsTotal; } private function generateNewVisit() { $this->setCurrentRequest( 'urlref' , $this->getRandom('urlref')); $this->setCurrentRequest( 'idsite', $this->getRandom('idsite')); $this->setCurrentRequest( 'res' ,$this->getRandom('res')); $this->setCurrentRequest( 'col' ,$this->getRandom('col')); $this->setCurrentRequest( 'h' ,$this->getRandom('h')); $this->setCurrentRequest( 'm' ,$this->getRandom('m')); $this->setCurrentRequest( 's' ,$this->getRandom('s')); $this->setCurrentRequest( 'fla' ,$this->getRandom01()); $this->setCurrentRequest( 'dir' ,$this->getRandom01()); $this->setCurrentRequest( 'qt' ,$this->getRandom01()); $this->setCurrentRequest( 'realp' ,$this->getRandom01()); $this->setCurrentRequest( 'pdf' ,$this->getRandom01()); $this->setCurrentRequest( 'wma' ,$this->getRandom01()); $this->setCurrentRequest( 'java' ,$this->getRandom01()); $this->setCurrentRequest( 'cookie',$this->getRandom01()); $_SERVER['HTTP_CLIENT_IP'] = mt_rand(0,255).".".mt_rand(0,255).".".mt_rand(0,255).".".mt_rand(0,255); $_SERVER['HTTP_USER_AGENT'] = $this->userAgents[mt_rand(0,count($this->userAgents)-1)]; $_SERVER['HTTP_ACCEPT_LANGUAGE'] = $this->acceptLanguage[mt_rand(0,count($this->acceptLanguage)-1)]; } private function generateActionVisit() { // we don't keep the previous action values // reinit them to empty string $this->setCurrentRequest( Piwik_LogStats_Config::getInstance()->LogStats['download_outlink_name_var'],''); $this->setCurrentRequest( Piwik_LogStats_Config::getInstance()->LogStats['download_url_var_name'],''); $this->setCurrentRequest( Piwik_LogStats_Config::getInstance()->LogStats['outlink_url_var_name'],''); $this->setCurrentRequest( 'action_name', ''); // generate new url referer ; case the visitor stays more than 30min // we set it as a new visit and the referer will then be used $this->setCurrentRequest( 'urlref' , $this->getRandom('urlref')); $url = $this->getRandomUrlFromHost($this->host); // we generate a campaign (partner or newsletter or campaign) $urlVars = $this->getRandom('piwik_vars_campaign'); // campaign name $urlValue = $this->getRandomString(5,3,'lower'); // if we actually generated a campaign if(!empty($urlVars)) { // add the parameter to the url $url .= '?'. $urlVars . '=' . $urlValue; // for a campaign of the CPC kind, we sometimes generate a keyword if($urlVars == Piwik_LogStats_Config::getInstance()->LogStats['campaign_var_name'] && mt_rand(0,1)==0) { $url .= '&'. Piwik_LogStats_Config::getInstance()->LogStats['campaign_keyword_var_name'] . '=' . $this->getRandomString(6,3,'ALL');; } } else { // we generate a download Or Outlink parameter in the GET request so that // the current action is counted as a download action OR a outlink click action $GETParamToAdd = $this->getRandom('piwik_downloadOrOutlink'); if(!empty($GETParamToAdd)) { // download / outlink url $urlValue = $this->getRandomUrlFromHost($this->host); // add the parameter to the url $this->setCurrentRequest( $GETParamToAdd , $urlValue); if(mt_rand(0,1)==0) { $this->setCurrentRequest( Piwik_LogStats_Config::getInstance()->LogStats['download_outlink_name_var'] , $this->getRandomString(6,3,'ALL')); } } else { if(rand(0,2)==1) { $this->setCurrentRequest( 'action_name' , $this->getRandomString(3,3)); } } } // print($url . "
"); $this->setCurrentRequest( 'url' ,$url); $this->setCurrentRequest( 'title',$this->getRandomString(15,5)); } private function getRandomUrlFromHost( $host ) { $url = $host; $deep = mt_rand(0,2); for($i=0;$i<$deep;$i++) { $name = $this->getRandomString(1,2,'alnum'); $url .= '/'.$name; } return $url; } // from php.net and edited private function getRandomString($maxLength = 15, $minLength = 5, $type = 'ALL') { $len = mt_rand($minLength, $maxLength); // Register the lower case alphabet array $alpha = array('a', 'b', 'c', 'd', 'e', 'f', 'g'); // Register the upper case alphabet array $ALPHA = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'); // Register the numeric array $num = array('1', '2', '3', '4', '5', '6', '7', '8', '9', '0'); // Register the strange array $strange = array('/', '?', '!','"','£','$','%','^','&','*','(',')',' '); // Initialize the keyVals array for use in the for loop $keyVals = array(); // Initialize the key array to register each char $key = array(); // Loop through the choices and register // The choice to keyVals array switch ($type) { case 'lower' : $keyVals = $alpha; break; case 'upper' : $keyVals = $ALPHA; break; case 'numeric' : $keyVals = $num; break; case 'ALPHA' : $keyVals = array_merge($alpha, $ALPHA); break; case 'alnum' : $keyVals = array_merge($alpha, $num); break; case 'ALNUM' : $keyVals = array_merge($alpha, $ALPHA, $num); break; case 'ALL' : $keyVals = array_merge($alpha, $ALPHA, $num, $strange); break; } // Loop as many times as specified // Register each value to the key array for($i = 0; $i <= $len-1; $i++) { $r = mt_rand(0,count($keyVals)-1); $key[$i] = $keyVals[$r]; } // Glue the key array into a string and return it return join("", $key); } private function setFakeRequest() { $_REQUEST = $_GET = $this->currentget; } private function setCurrentRequest($name,$value) { $this->currentget[$name] = $value; } private function getRandom( $name ) { if(!isset($this->allget[$name])) { throw new exception("You are asking for $name which doesnt exist"); } else { $index = mt_rand(0,count($this->allget[$name])-1); $value =$this->allget[$name][$index]; return $value; } } private function getRandom01() { return mt_rand(0,1); } private function saveVisit() { $this->setFakeRequest(); $process = new Piwik_LogStats_Generator_Main; $process->main('Piwik_LogStats_Generator_Visit'); } } class Piwik_LogStats_Generator_Main extends Piwik_LogStats { protected function sendHeader($header) { // header($header); } } class Piwik_LogStats_Generator_Visit extends Piwik_LogStats_Visit { static protected $timestampToUse; function __construct( $db ) { parent::__construct($db); } static public function setTimestampToUse($time) { self::$timestampToUse = $time; } protected function getCurrentDate( $format = "Y-m-d") { return date($format, $this->getCurrentTimestamp() ); } protected function getCurrentTimestamp() { self::$timestampToUse = max(@$this->visitorInfo['visit_last_action_time'],self::$timestampToUse); self::$timestampToUse += mt_rand(4,1840); return self::$timestampToUse; } protected function getDatetimeFromTimestamp($timestamp) { return date("Y-m-d H:i:s",$timestamp); } } ?>