mirror of
https://github.com/Mibew/java.git
synced 2025-01-22 17:40:35 +03:00
Refactor cron_calculate_statistics function
This commit is contained in:
parent
a7ce1ff704
commit
289fb76906
@ -19,6 +19,7 @@
|
|||||||
require_once('libs/init.php');
|
require_once('libs/init.php');
|
||||||
require_once('libs/classes/thread.php');
|
require_once('libs/classes/thread.php');
|
||||||
require_once('libs/track.php');
|
require_once('libs/track.php');
|
||||||
|
require_once('libs/statistics.php');
|
||||||
require_once('libs/cron.php');
|
require_once('libs/cron.php');
|
||||||
|
|
||||||
$cron_key = empty($_GET['cron_key']) ? '' : $_GET['cron_key'];
|
$cron_key = empty($_GET['cron_key']) ? '' : $_GET['cron_key'];
|
||||||
@ -32,7 +33,11 @@ set_time_limit(0);
|
|||||||
|
|
||||||
// Run cron jobs of the core
|
// Run cron jobs of the core
|
||||||
cron_index_messages();
|
cron_index_messages();
|
||||||
cron_calculate_statistics();
|
|
||||||
|
calculate_thread_statistics();
|
||||||
|
calculate_operator_statistics();
|
||||||
|
calculate_page_statistics();
|
||||||
|
|
||||||
|
|
||||||
// Trigger cron event
|
// Trigger cron event
|
||||||
$dispatcher = EventDispatcher::getInstance();
|
$dispatcher = EventDispatcher::getInstance();
|
||||||
|
@ -202,204 +202,6 @@ function cron_index_messages() {
|
|||||||
$db->query('COMMIT');
|
$db->query('COMMIT');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate aggregated 'by thread' and 'by operator' statistics
|
|
||||||
*/
|
|
||||||
function cron_calculate_statistics() {
|
|
||||||
// Prepare database
|
|
||||||
$db = Database::getInstance();
|
|
||||||
$db->throwExeptions(true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Start transaction
|
|
||||||
$db->query('START TRANSACTION');
|
|
||||||
|
|
||||||
// Build 'by thread' statistics
|
|
||||||
// Get last record date
|
|
||||||
$result = $db->query(
|
|
||||||
"SELECT MAX(date) as start FROM {chatthreadstatistics}",
|
|
||||||
array(),
|
|
||||||
array('return_rows' => Database::RETURN_ONE_ROW)
|
|
||||||
);
|
|
||||||
|
|
||||||
$start = empty($result['start']) ? 0 : $result['start'];
|
|
||||||
|
|
||||||
// Reset statistics for the last day, because cron can be ran many
|
|
||||||
// times in a day.
|
|
||||||
$result = $db->query(
|
|
||||||
"DELETE FROM {chatthreadstatistics} WHERE date = :start",
|
|
||||||
array(':start' => $start)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Calculate 'by thread' statistics
|
|
||||||
$db->query(
|
|
||||||
"INSERT INTO {chatthreadstatistics} ( " .
|
|
||||||
"date, threads, operatormessages, usermessages, " .
|
|
||||||
"averagewaitingtime, averagechattime " .
|
|
||||||
") SELECT (FLOOR(t.dtmcreated / (24*60*60)) * 24*60*60) AS date, " .
|
|
||||||
"COUNT(distinct t.threadid) AS threads, " .
|
|
||||||
"SUM(m.ikind = :kind_agent) AS operators, " .
|
|
||||||
"SUM(m.ikind = :kind_user) AS users, " .
|
|
||||||
"ROUND(AVG(t.dtmchatstarted-t.dtmcreated),1) as avgwaitingtime, " .
|
|
||||||
// Prevent negative values of avgchattime field.
|
|
||||||
// If avgchattime < 0 it becomes to zero.
|
|
||||||
// For random value 'a' result of expression ((abs(a) + a) / 2)
|
|
||||||
// equals to 'a' if 'a' more than zero
|
|
||||||
// and equals to zero otherwise
|
|
||||||
"ROUND(AVG( " .
|
|
||||||
"ABS(tmp.lastmsgtime-t.dtmchatstarted) + " .
|
|
||||||
"(tmp.lastmsgtime-t.dtmchatstarted) " .
|
|
||||||
")/2,1) as avgchattime " .
|
|
||||||
"FROM {indexedchatmessage} m, " .
|
|
||||||
"{chatthread} t, " .
|
|
||||||
"(SELECT i.threadid, MAX(i.dtmcreated) AS lastmsgtime " .
|
|
||||||
"FROM {indexedchatmessage} i " .
|
|
||||||
"WHERE (ikind = :kind_user OR ikind = :kind_agent) " .
|
|
||||||
"GROUP BY i.threadid) tmp " .
|
|
||||||
"WHERE m.threadid = t.threadid " .
|
|
||||||
"AND tmp.threadid = t.threadid " .
|
|
||||||
"AND t.dtmchatstarted <> 0 " .
|
|
||||||
"AND m.dtmcreated > :start " .
|
|
||||||
"GROUP BY date " .
|
|
||||||
"ORDER BY date",
|
|
||||||
array(
|
|
||||||
':kind_agent' => Thread::KIND_AGENT,
|
|
||||||
':kind_user' => Thread::KIND_USER,
|
|
||||||
':start' => $start
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Build 'by operator' statistics
|
|
||||||
// Get last record date
|
|
||||||
$result = $db->query(
|
|
||||||
"SELECT MAX(date) as start FROM {chatoperatorstatistics}",
|
|
||||||
array(),
|
|
||||||
array('return_rows' => Database::RETURN_ONE_ROW)
|
|
||||||
);
|
|
||||||
|
|
||||||
$start = empty($result['start']) ? 0 : $result['start'];
|
|
||||||
|
|
||||||
// Reset statistics for the last day, because cron can be ran many
|
|
||||||
// times in a day.
|
|
||||||
$result = $db->query(
|
|
||||||
"DELETE FROM {chatoperatorstatistics} WHERE date = :start",
|
|
||||||
array(':start' => $start)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Caclculate 'by operator' statistics
|
|
||||||
$db->query(
|
|
||||||
"INSERT INTO {chatoperatorstatistics} ( " .
|
|
||||||
"date, operatorid, threads, messages, averagelength" .
|
|
||||||
") SELECT (FLOOR(m.dtmcreated / (24*60*60)) * 24*60*60) AS date, " .
|
|
||||||
"o.operatorid AS opid, " .
|
|
||||||
"COUNT(distinct m.threadid) AS threads, " .
|
|
||||||
"SUM(m.ikind = :kind_agent) AS msgs, " .
|
|
||||||
"AVG(CHAR_LENGTH(m.tmessage)) AS avglen " .
|
|
||||||
"FROM {indexedchatmessage} m, {chatoperator} o " .
|
|
||||||
"WHERE m.agentId = o.operatorid " .
|
|
||||||
"AND m.dtmcreated > :start " .
|
|
||||||
"GROUP BY date " .
|
|
||||||
"ORDER BY date",
|
|
||||||
array(
|
|
||||||
':kind_agent' => Thread::KIND_AGENT,
|
|
||||||
':start' => $start
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Build 'by page' statistics
|
|
||||||
$visited_pages = $db->query(
|
|
||||||
"SELECT FLOOR(p.visittime / (24*60*60)) * 24*60*60 AS date, " .
|
|
||||||
"p.address AS address, " .
|
|
||||||
// 'visittimes' is not calculated pages count. It means that
|
|
||||||
// 'visittimes' is count of NEW visited pages, not total count.
|
|
||||||
"COUNT(DISTINCT p.pageid) AS visittimes, " .
|
|
||||||
// 'chattimes' is total count of threads related with a page
|
|
||||||
// address, not a visited page row. It means that 'chattimes' is
|
|
||||||
// TOTAL chats count from this page, not only new.
|
|
||||||
"COUNT(DISTINCT t.threadid) AS chattimes " .
|
|
||||||
"FROM {visitedpage} p " .
|
|
||||||
"LEFT OUTER JOIN {chatthread} t ON (" .
|
|
||||||
"p.address = t.referer " .
|
|
||||||
"AND DATE(FROM_UNIXTIME(p.visittime)) = " .
|
|
||||||
"DATE(FROM_UNIXTIME(t.dtmcreated))) " .
|
|
||||||
"WHERE p.calculated = 0 " .
|
|
||||||
"GROUP BY date, address " .
|
|
||||||
"ORDER BY date",
|
|
||||||
array(),
|
|
||||||
array('return_rows' => Database::RETURN_ALL_ROWS)
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach($visited_pages as $visited_page) {
|
|
||||||
// Check is there statistics for current visited page in database.
|
|
||||||
$count_result = $db->query(
|
|
||||||
"SELECT COUNT(*) AS count " .
|
|
||||||
"FROM {visitedpagestatistics} " .
|
|
||||||
"WHERE date = :date AND address = :address",
|
|
||||||
array(
|
|
||||||
':date' => $visited_page['date'],
|
|
||||||
':address' => $visited_page['address']
|
|
||||||
),
|
|
||||||
array('return_rows' => Database::RETURN_ONE_ROW)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (! empty($count_result['count'])) {
|
|
||||||
// Stat already in database. Update it.
|
|
||||||
$db->query(
|
|
||||||
"UPDATE {visitedpagestatistics} SET " .
|
|
||||||
"visits = visits + :visits, " .
|
|
||||||
// Do not add chat because of it is total count of chats
|
|
||||||
// related with this page.
|
|
||||||
// TODO: Think about old threads removing. In current
|
|
||||||
// configuration it can cause problems with wrong
|
|
||||||
// 'by page' statistics.
|
|
||||||
"chats = :chats " .
|
|
||||||
"WHERE date = :date " .
|
|
||||||
"AND address = :address " .
|
|
||||||
"LIMIT 1",
|
|
||||||
array(
|
|
||||||
':date' => $visited_page['date'],
|
|
||||||
':address' => $visited_page['address'],
|
|
||||||
':visits' => $visited_page['visittimes'],
|
|
||||||
':chats' => $visited_page['chattimes']
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// Create stat row in database.
|
|
||||||
$db->query(
|
|
||||||
"INSERT INTO {visitedpagestatistics} (" .
|
|
||||||
"date, address, visits, chats" .
|
|
||||||
") VALUES ( " .
|
|
||||||
":date, :address, :visits, :chats" .
|
|
||||||
")",
|
|
||||||
array(
|
|
||||||
':date' => $visited_page['date'],
|
|
||||||
':address' => $visited_page['address'],
|
|
||||||
':visits' => $visited_page['visittimes'],
|
|
||||||
':chats' => $visited_page['chattimes']
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark all visited pages as 'calculated'
|
|
||||||
$db->query("UPDATE {visitedpage} SET calculated = 1");
|
|
||||||
|
|
||||||
// Remove old tracks from the system
|
|
||||||
track_remove_old_tracks();
|
|
||||||
} catch(Exception $e) {
|
|
||||||
// Something went wrong: warn and rollback transaction.
|
|
||||||
trigger_error(
|
|
||||||
'Statistics calculating faild: ' . $e->getMessage(),
|
|
||||||
E_USER_WARNING
|
|
||||||
);
|
|
||||||
$db->query('ROLLBACK');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Commit transaction
|
|
||||||
$db->query('COMMIT');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates cron URI
|
* Generates cron URI
|
||||||
*
|
*
|
||||||
|
@ -39,4 +39,249 @@ function setup_statistics_tabs($active)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate aggregated 'by thread' statistics
|
||||||
|
*/
|
||||||
|
function calculate_thread_statistics() {
|
||||||
|
// Prepare database
|
||||||
|
$db = Database::getInstance();
|
||||||
|
$db->throwExeptions(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Start transaction
|
||||||
|
$db->query('START TRANSACTION');
|
||||||
|
|
||||||
|
// Get last record date
|
||||||
|
$result = $db->query(
|
||||||
|
"SELECT MAX(date) as start FROM {chatthreadstatistics}",
|
||||||
|
array(),
|
||||||
|
array('return_rows' => Database::RETURN_ONE_ROW)
|
||||||
|
);
|
||||||
|
|
||||||
|
$start = empty($result['start']) ? 0 : $result['start'];
|
||||||
|
|
||||||
|
// Reset statistics for the last day, because cron can be ran many
|
||||||
|
// times in a day.
|
||||||
|
$result = $db->query(
|
||||||
|
"DELETE FROM {chatthreadstatistics} WHERE date = :start",
|
||||||
|
array(':start' => $start)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Calculate statistics
|
||||||
|
$db->query(
|
||||||
|
"INSERT INTO {chatthreadstatistics} ( " .
|
||||||
|
"date, threads, operatormessages, usermessages, " .
|
||||||
|
"averagewaitingtime, averagechattime " .
|
||||||
|
") SELECT (FLOOR(t.dtmcreated / (24*60*60)) * 24*60*60) AS date, " .
|
||||||
|
"COUNT(distinct t.threadid) AS threads, " .
|
||||||
|
"SUM(m.ikind = :kind_agent) AS operators, " .
|
||||||
|
"SUM(m.ikind = :kind_user) AS users, " .
|
||||||
|
"ROUND(AVG(t.dtmchatstarted-t.dtmcreated),1) as avgwaitingtime, " .
|
||||||
|
// Prevent negative values of avgchattime field.
|
||||||
|
// If avgchattime < 0 it becomes to zero.
|
||||||
|
// For random value 'a' result of expression ((abs(a) + a) / 2)
|
||||||
|
// equals to 'a' if 'a' more than zero
|
||||||
|
// and equals to zero otherwise
|
||||||
|
"ROUND(AVG( " .
|
||||||
|
"ABS(tmp.lastmsgtime-t.dtmchatstarted) + " .
|
||||||
|
"(tmp.lastmsgtime-t.dtmchatstarted) " .
|
||||||
|
")/2,1) as avgchattime " .
|
||||||
|
"FROM {indexedchatmessage} m, " .
|
||||||
|
"{chatthread} t, " .
|
||||||
|
"(SELECT i.threadid, MAX(i.dtmcreated) AS lastmsgtime " .
|
||||||
|
"FROM {indexedchatmessage} i " .
|
||||||
|
"WHERE (ikind = :kind_user OR ikind = :kind_agent) " .
|
||||||
|
"GROUP BY i.threadid) tmp " .
|
||||||
|
"WHERE m.threadid = t.threadid " .
|
||||||
|
"AND tmp.threadid = t.threadid " .
|
||||||
|
"AND t.dtmchatstarted <> 0 " .
|
||||||
|
"AND m.dtmcreated > :start " .
|
||||||
|
"GROUP BY date " .
|
||||||
|
"ORDER BY date",
|
||||||
|
array(
|
||||||
|
':kind_agent' => Thread::KIND_AGENT,
|
||||||
|
':kind_user' => Thread::KIND_USER,
|
||||||
|
':start' => $start
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} catch(Exception $e) {
|
||||||
|
// Something went wrong: warn and rollback transaction.
|
||||||
|
trigger_error(
|
||||||
|
'Thread statistics calculating faild: ' . $e->getMessage(),
|
||||||
|
E_USER_WARNING
|
||||||
|
);
|
||||||
|
$db->query('ROLLBACK');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit transaction
|
||||||
|
$db->query('COMMIT');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate aggregated 'by operator' statistics
|
||||||
|
*/
|
||||||
|
function calculate_operator_statistics() {
|
||||||
|
// Prepare database
|
||||||
|
$db = Database::getInstance();
|
||||||
|
$db->throwExeptions(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Start transaction
|
||||||
|
$db->query('START TRANSACTION');
|
||||||
|
|
||||||
|
// Get last record date
|
||||||
|
$result = $db->query(
|
||||||
|
"SELECT MAX(date) as start FROM {chatoperatorstatistics}",
|
||||||
|
array(),
|
||||||
|
array('return_rows' => Database::RETURN_ONE_ROW)
|
||||||
|
);
|
||||||
|
|
||||||
|
$start = empty($result['start']) ? 0 : $result['start'];
|
||||||
|
|
||||||
|
// Reset statistics for the last day, because cron can be ran many
|
||||||
|
// times in a day.
|
||||||
|
$result = $db->query(
|
||||||
|
"DELETE FROM {chatoperatorstatistics} WHERE date = :start",
|
||||||
|
array(':start' => $start)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Caclculate statistics
|
||||||
|
$db->query(
|
||||||
|
"INSERT INTO {chatoperatorstatistics} ( " .
|
||||||
|
"date, operatorid, threads, messages, averagelength" .
|
||||||
|
") SELECT (FLOOR(m.dtmcreated / (24*60*60)) * 24*60*60) AS date, " .
|
||||||
|
"o.operatorid AS opid, " .
|
||||||
|
"COUNT(distinct m.threadid) AS threads, " .
|
||||||
|
"SUM(m.ikind = :kind_agent) AS msgs, " .
|
||||||
|
"AVG(CHAR_LENGTH(m.tmessage)) AS avglen " .
|
||||||
|
"FROM {indexedchatmessage} m, {chatoperator} o " .
|
||||||
|
"WHERE m.agentId = o.operatorid " .
|
||||||
|
"AND m.dtmcreated > :start " .
|
||||||
|
"GROUP BY date " .
|
||||||
|
"ORDER BY date",
|
||||||
|
array(
|
||||||
|
':kind_agent' => Thread::KIND_AGENT,
|
||||||
|
':start' => $start
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} catch(Exception $e) {
|
||||||
|
// Something went wrong: warn and rollback transaction.
|
||||||
|
trigger_error(
|
||||||
|
'Operator statistics calculating faild: ' . $e->getMessage(),
|
||||||
|
E_USER_WARNING
|
||||||
|
);
|
||||||
|
$db->query('ROLLBACK');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit transaction
|
||||||
|
$db->query('COMMIT');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate aggregated 'by page' statistics
|
||||||
|
*/
|
||||||
|
function calculate_page_statistics() {
|
||||||
|
// Prepare database
|
||||||
|
$db = Database::getInstance();
|
||||||
|
$db->throwExeptions(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Start transaction
|
||||||
|
$db->query('START TRANSACTION');
|
||||||
|
|
||||||
|
$visited_pages = $db->query(
|
||||||
|
"SELECT FLOOR(p.visittime / (24*60*60)) * 24*60*60 AS date, " .
|
||||||
|
"p.address AS address, " .
|
||||||
|
// 'visittimes' is not calculated pages count. It means that
|
||||||
|
// 'visittimes' is count of NEW visited pages, not total count.
|
||||||
|
"COUNT(DISTINCT p.pageid) AS visittimes, " .
|
||||||
|
// 'chattimes' is total count of threads related with a page
|
||||||
|
// address, not a visited page row. It means that 'chattimes' is
|
||||||
|
// TOTAL chats count from this page, not only new.
|
||||||
|
"COUNT(DISTINCT t.threadid) AS chattimes " .
|
||||||
|
"FROM {visitedpage} p " .
|
||||||
|
"LEFT OUTER JOIN {chatthread} t ON (" .
|
||||||
|
"p.address = t.referer " .
|
||||||
|
"AND DATE(FROM_UNIXTIME(p.visittime)) = " .
|
||||||
|
"DATE(FROM_UNIXTIME(t.dtmcreated))) " .
|
||||||
|
"WHERE p.calculated = 0 " .
|
||||||
|
"GROUP BY date, address " .
|
||||||
|
"ORDER BY date",
|
||||||
|
array(),
|
||||||
|
array('return_rows' => Database::RETURN_ALL_ROWS)
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach($visited_pages as $visited_page) {
|
||||||
|
// Check is there statistics for current visited page in database.
|
||||||
|
$count_result = $db->query(
|
||||||
|
"SELECT COUNT(*) AS count " .
|
||||||
|
"FROM {visitedpagestatistics} " .
|
||||||
|
"WHERE date = :date AND address = :address",
|
||||||
|
array(
|
||||||
|
':date' => $visited_page['date'],
|
||||||
|
':address' => $visited_page['address']
|
||||||
|
),
|
||||||
|
array('return_rows' => Database::RETURN_ONE_ROW)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (! empty($count_result['count'])) {
|
||||||
|
// Stat already in database. Update it.
|
||||||
|
$db->query(
|
||||||
|
"UPDATE {visitedpagestatistics} SET " .
|
||||||
|
"visits = visits + :visits, " .
|
||||||
|
// Do not add chat because of it is total count of chats
|
||||||
|
// related with this page.
|
||||||
|
// TODO: Think about old threads removing. In current
|
||||||
|
// configuration it can cause problems with wrong
|
||||||
|
// 'by page' statistics.
|
||||||
|
"chats = :chats " .
|
||||||
|
"WHERE date = :date " .
|
||||||
|
"AND address = :address " .
|
||||||
|
"LIMIT 1",
|
||||||
|
array(
|
||||||
|
':date' => $visited_page['date'],
|
||||||
|
':address' => $visited_page['address'],
|
||||||
|
':visits' => $visited_page['visittimes'],
|
||||||
|
':chats' => $visited_page['chattimes']
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Create stat row in database.
|
||||||
|
$db->query(
|
||||||
|
"INSERT INTO {visitedpagestatistics} (" .
|
||||||
|
"date, address, visits, chats" .
|
||||||
|
") VALUES ( " .
|
||||||
|
":date, :address, :visits, :chats" .
|
||||||
|
")",
|
||||||
|
array(
|
||||||
|
':date' => $visited_page['date'],
|
||||||
|
':address' => $visited_page['address'],
|
||||||
|
':visits' => $visited_page['visittimes'],
|
||||||
|
':chats' => $visited_page['chattimes']
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark all visited pages as 'calculated'
|
||||||
|
$db->query("UPDATE {visitedpage} SET calculated = 1");
|
||||||
|
|
||||||
|
// Remove old tracks from the system
|
||||||
|
track_remove_old_tracks();
|
||||||
|
} catch(Exception $e) {
|
||||||
|
// Something went wrong: warn and rollback transaction.
|
||||||
|
trigger_error(
|
||||||
|
'Page statistics calculating faild: ' . $e->getMessage(),
|
||||||
|
E_USER_WARNING
|
||||||
|
);
|
||||||
|
$db->query('ROLLBACK');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit transaction
|
||||||
|
$db->query('COMMIT');
|
||||||
|
}
|
||||||
|
|
||||||
?>
|
?>
|
Loading…
Reference in New Issue
Block a user