pp3/au/build-dashboard_v2.php (270 lines of code) (raw):
#!/usr/bin/php
<?php
/**
* Script for calculation of AU dashboard numbers from pings, users... tables
*
* Some background: dlc+nb logfiles are parsed for IDE callbacks to catalog.xml
* and those pings are analyzed and inserted into DB, tables pings, users, catalogs, releases...
* There is enourmous number of these records - hundrets of millions.
* This script then calculates basic stats from these numbers and saves result
* to DB again so we can use them on dashboard later on.
*
* CLI options:
* --month=yyyy-mm month for which generate numbers
* --debug
* --help
*
*/
// Connection config, edit to match your env
$connection = array(
'driver' => 'mysqli',
'host' => '127.0.0.1',
'username' => 'jchalupa',
'password' => '',
'database' => 'root',
'profiler' => TRUE,
);
// manual delay in days for counting data
$delay = 2;
// debug flag
$debug = false;
// lockfile
$lockfile = './tmp/run.lck';
/*
* == DO NOT EDIT BELOW THIS LINE UNLESS YOU ARE SURE YOU KNOW WHAT YOU ARE DOING ==
*/
// read params from cli
require_once './lib/Getopt.php';
try {
$opts = new Zend_Console_Getopt(array('help|h' => 'Show help',
'month|m=s' => 'Month for which generate stats, format yyyy-mm',
'debug|d' => 'Show debug output',
'product|p=s' => 'Product - netbeans, vvm',
'stat|s=s' => 'Statistic to run - au, au2, countries, distros, packs, stickiness'));
$opts->parse();
$month = $opts->getOption('month');
$debug = $opts->getOption('debug');
$help = $opts->getOption('help');
$product = $opts->getOption('product');
$stat = ($opts->getOption('stat')) ? $opts->getOption('stat') : 'all';
if ($help) {
echo $opts->getUsageMessage();
exit(0);
}
} catch (Zend_Console_Exception $e) {
echo $opts->getUsageMessage();
exit(1);
}
if (!file_exists($lockfile)) {
// lock the run
exec('touch ' . $lockfile);
echo "Lockfile created\n";
// use delayed value from today if it's not defined from cli
if (empty($month))
$month = date('Y-m', strtotime('-' . $delay . ' day'));
if (empty($product))
$product = 'netbeans';
// let's use DIBI for db abstraction, Uff there is PHP version check failure on nina.cz.oracle.com
//require_once(dirname(__FILE__) . "/include/dibi.min.php");
try {
//dibi::connect($connection);
require_once './db_connect.php.inc';
// setup stats params like dates and offsets
switch ($product) {
case 'netbeans':
$activityOffset = 7;
$monthStart = $month; // users counted monthly
break;
case 'vvm':
$activityOffset = 7;
$monthStart = date('Y-m', strtotime('-1 year', strtotime($month . '-01'))); // users counted yearly
break;
default:
$activityOffset = 7;
$monthStart = $month;
break;
}
// now put together statistics, query DB and insert results
if ($stat == 'all') {
au($month, $product, $activityOffset, $monthStart);
au2($month, $product, $activityOffset, $monthStart);
//countries($month, $product, $activityOffset, $monthStart);
//distros($month, $product, $activityOffset, $monthStart);
//packs($month, $product, $activityOffset, $monthStart);
//stickiness($month, $product);
} else {
$stat($month, $product, $activityOffset, $monthStart);
}
} catch (Exception $e) {
echo $e->getMessage() . "\n";
unlock();
exit(1);
}
unlock();
exit(0);
} else {
echo "Previous run of the script seems to be still running, lockfile found: " . $lockfile . " from " . date('F d Y H:i:s', filemtime($lockfile)) . "\nRemove lockfile first!\n";
}
function unlock() {
global $lockfile;
unlink($lockfile);
echo "\nLockfile removed\n";
}
/*
* Active Users for selected month, by releases
*/
function au($month, $product, $activityOffset, $monthStart) {
global $dbc, $debug;
$qr = 'SELECT COUNT(DISTINCT p.user_id) AS count, r.id AS release_id, r.version AS release_version, r.lang
FROM pings p
INNER JOIN users u
ON (p.user_id=u.id AND p.ts BETWEEN "' . $monthStart . '-01" AND "' . $month . '-31 23:59:59")
INNER JOIN catalogs c
ON (p.path_id=c.id AND p.ts BETWEEN "' . $monthStart . '-01" AND "' . $month . '-31 23:59:59")
INNER JOIN releases r
ON (r.catalog_id=c.id AND r.product="' . $product . '")
WHERE IF(r.delay="Y", DATEDIFF(p.ts,u.since)>=' . $activityOffset . ', TRUE)
GROUP BY r.id';
try {
echo "Number of $product Active Users by release version for month $month\n";
if ($debug)
echo "Debug: " . $qr . "\n\n";
$res = mysqli_query($dbc, $qr);
echo "Found " . mysqli_num_rows($res) . " items\n";
while ($r = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
// we have some data, let's insert into db
echo "\t" . $r['release_version'] . " " . $r['lang'] . " : " . $r['count'] . " users\n";
$qr = 'REPLACE INTO results_counts SET month="' . $month . '", release_id=' . $r['release_id'] . ', results_index_id=1, value="' . $r['count'] . '", product="' . $product . '", pack_signature=0, distro_id=0, country_id=0';
$res2 = mysqli_query($dbc, $qr);
if (!$res2) {
echo "ERR: " . mysqli_error($dbc) . $qr . "\n";
}
}
} catch (Exception $e) {
echo 'Failed Query: ' . $e->getMessage();
}
}
function au2($month, $product, $activityOffset, $monthStart) {
global $dbc, $debug;
$qr = 'SELECT COUNT(DISTINCT p.user2_id) AS count, r.id AS release_id, r.version AS release_version, r.lang
FROM pings p
INNER JOIN users2 u
ON (p.user2_id=u.id AND p.ts BETWEEN "' . $monthStart . '-01" AND "' . $month . '-31 23:59:59")
INNER JOIN catalogs c
ON (p.path_id=c.id AND p.ts BETWEEN "' . $monthStart . '-01" AND "' . $month . '-31 23:59:59")
INNER JOIN releases r
ON (r.catalog_id=c.id AND r.product="' . $product . '")
WHERE IF(r.delay="Y", DATEDIFF(p.ts,u.since)>=' . $activityOffset . ', TRUE)
GROUP BY r.id';
try {
echo "Number of $product UNIQUE Active Users by release version for month $month\n";
if ($debug)
echo "Debug: " . $qr . "\n\n";
$res = mysqli_query($dbc, $qr);
echo "Found " . mysqli_num_rows($res) . " items\n";
while ($r = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
// we have some data, let's insert into db
echo "\t" . $r['release_version'] . " " . $r['lang'] . " : " . $r['count'] . " users\n";
$qr = 'REPLACE INTO results_counts SET month="' . $month . '", release_id=' . $r['release_id'] . ', results_index_id=3, value="' . $r['count'] . '", product="' . $product . '", country_id=0, pack_signature=0, distro_id=0';
$res2 = mysqli_query($dbc, $qr);
if (!$res2) {
echo "ERR: " . mysqli_error($dbc) . $qr . "\n";
}
}
} catch (Exception $e) {
echo 'Failed Query: ' . $e->getMessage();
}
}
/**
* Active users for selected month by countries
*/
function countries($month, $product, $activityOffset, $monthStart) {
global $dbc, $debug;
$qr = 'SELECT COUNT(DISTINCT p.user_id) AS count, ctr.name AS country_name, ctr.id as country_id
FROM pings p
INNER JOIN users u
ON (p.user_id=u.id AND p.ts BETWEEN "' . $monthStart . '-01" AND "' . $month . '-31 23:59:59")
INNER JOIN catalogs c
ON (p.path_id=c.id AND p.ts BETWEEN "' . $monthStart . '-01" AND "' . $month . '-31 23:59:59")
INNER JOIN releases r
ON (r.catalog_id=c.id AND r.product="' . $product . '")
INNER JOIN ips i
ON p.ip_id=i.id AND p.ts BETWEEN "' . $monthStart . '-01" AND "' . $month . '-31 23:59:59"
INNER JOIN countries ctr
ON ctr.code=i.country
WHERE IF(r.delay="Y", DATEDIFF(p.ts,u.since)>=' . $activityOffset . ', TRUE)
GROUP BY i.country ORDER BY count DESC';
try {
echo "\n\nNumber of $product Active users by countries for month $month\n";
if ($debug)
echo "Debug: " . $qr . "\n\n";
$res = mysqli_query($dbc, $qr);
echo "Found " . count($res) . " items\n";
while ($r = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
// we have some data, let's insert into db
echo "\t" . $r['country_name'] . ": " . $r['count'] . " users\n";
$qr = 'REPLACE INTO results_counts SET month="' . $month . '", country_id=' . $r['country_id'] . ', results_index_id=2, value="' . $r['count'] . '", product="' . $product . '", release_id=0, distro_id=0, pack_signature=0';
$res2 = mysqli_query($dbc, $qr);
if (!$res2) {
echo "ERR: " . mysqli_error($dbc) . $qr . "\n";
}
}
} catch (Exception $e) {
echo 'Failed Query: ' . $e->getMessage();
}
}
function distros($month, $product, $activityOffset, $monthStart) {
global $dbc, $debug;
$qr = 'SELECT COUNT(DISTINCT p.user2_id) AS count, d.id AS distro_id, d.distro
FROM pings p
INNER JOIN users2 u
ON (p.user2_id=u.id AND p.ts BETWEEN "' . $monthStart . '-01" AND "' . $month . '-31 23:59:59")
INNER JOIN catalogs c
ON (p.path_id=c.id AND p.ts BETWEEN "' . $monthStart . '-01" AND "' . $month . '-31 23:59:59")
INNER JOIN releases r
ON (r.catalog_id=c.id AND r.product="' . $product . '")
INNER JOIN distros d ON (d.id=p.distro_id AND p.ts BETWEEN "' . $monthStart . '-01" AND "' . $month . '-31 23:59:59")
WHERE IF(r.delay="Y", DATEDIFF(p.ts,u.since)>=' . $activityOffset . ', TRUE)
GROUP BY d.id';
try {
echo "Number of $product Active Users by distribution for month $month\n";
if ($debug)
echo "Debug: " . $qr . "\n\n";
$res = mysqli_query($dbc, $qr);
echo "Found " . mysqli_num_rows($res) . " items\n";
while ($r = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
// we have some data, let's insert into db
echo "\t" . $r['distro'] . " : " . $r['count'] . " users\n";
$qr = 'REPLACE INTO results_counts SET month="' . $month . '", distro_id=' . $r['distro_id'] . ', results_index_id=4, value="' . $r['count'] . '", product="' . $product . '", release_id=0, pack_signature=0, country_id=0';
$res2 = mysqli_query($dbc, $qr);
if (!$res2) {
echo "ERR: " . mysqli_error($dbc) . $qr . "\n";
}
}
} catch (Exception $e) {
echo 'Failed Query: ' . $e->getMessage();
}
}
function packs($month, $product, $activityOffset, $monthStart) {
global $dbc, $debug;
$signatures = array('CND', 'CRE', 'ENT', 'MOB', 'PROF', 'CDC', 'CLDC', 'JAVA', 'JAVASE', 'JAVAEE', 'JAVAME', 'WEBEE', 'PROFILER',
'PHP', 'RUBY', 'MOBILITY', 'UML', 'SOA', 'GLASSFISH', 'SJSAS', 'TOMCAT', 'VISUALWEB', 'JDK', 'MYSQL',
'GROOVY', 'GFMOD', 'JAVAFX', 'WEBCOMMON', 'FX', 'PY', 'JC', 'WEBLOGIC');
$qr = 'SELECT COUNT(DISTINCT p.user2_id) AS count, cf.id AS config_id, cf.signature
FROM pings p
INNER JOIN users2 u
ON (p.user2_id=u.id AND p.ts BETWEEN "' . $monthStart . '-01" AND "' . $month . '-31 23:59:59")
INNER JOIN catalogs c
ON (p.path_id=c.id AND p.ts BETWEEN "' . $monthStart . '-01" AND "' . $month . '-31 23:59:59")
INNER JOIN releases r
ON (r.catalog_id=c.id AND r.product="' . $product . '")
INNER JOIN configs cf ON (cf.id=p.config_id AND p.ts BETWEEN "' . $monthStart . '-01" AND "' . $month . '-31 23:59:59")
WHERE IF(r.delay="Y", DATEDIFF(p.ts,u.since)>=' . $activityOffset . ', TRUE)
GROUP BY cf.id';
try {
echo "Number of $product Active Users by packs for month $month\n";
if ($debug)
echo "Debug: " . $qr . "\n\n";
$res = mysqli_query($dbc, $qr);
echo "Found " . mysqli_num_rows($res) . " items\n";
while ($r = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
// we have some data, let's count - parse the signature for packs and increment each pack according to it
$packs = explode(',', $r['signature']);
foreach ($packs as $pack) {
@$packsHits[$pack]+=$r['count'];
}
}
foreach ($packsHits as $pack => $hits) {
$qr = 'REPLACE INTO results_counts SET pack_signature="' . $pack . '", month="' . $month . '", results_index_id=5, value="' . $hits . '", product="' . $product . '", distro_id=0, release_id=0, country_id=0';
$res2 = mysqli_query($dbc, $qr);
echo "\t" . $pack . " : " . $hits . " users\n";
if (!$res2) {
echo "ERR: " . mysqli_error($dbc) . $qr . "\n";
}
}
} catch (Exception $e) {
echo 'Failed Query: ' . $e->getMessage();
}
}
function stickiness($month, $product) {
global $dbc, $debug;
// find all final releases and for each get the stickiness distribution
$releases = array();
$qr = 'SELECT * FROM releases WHERE product="' . $product . '" AND stable="Y"';
$res = mysqli_query($dbc, $qr);
while ($r = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
$releases[$r['version']][$r['id']] = $r['catalog_id'];
}
//die(var_dump($releases));
if (!empty($releases)) {
echo "Found " . count($releases) . " stable releases\n";
foreach ($releases as $version => $catalogs) {
// now query for for stickiness distribution
$qr = 'SELECT delay, count(id) as users FROM users WHERE catalog_id in (' . implode(',', $catalogs) . ') AND delay<90 and last_seen>='.strtotime('-90 days').' GROUP BY delay ORDER BY delay';
$res2 = mysqli_query($dbc, $qr);
$data = array();
while ($r2 = mysqli_fetch_array($res2, MYSQLI_ASSOC)) {
$data[$r2['delay']] = $r2['users'];
}
if(!empty($data)) {
// store it
echo 'Storing results for release '.$version."\n";
$qr = 'REPLACE INTO results_counts SET month="' . $month . '", results_index_id=6, value="' . addslashes(serialize($data)) . '", product="' . $product . '", distro_id=0, release_id='. key($catalogs).', country_id=0, pack_signature="0"';
$res2 = mysqli_query($dbc, $qr);
}
}
} else {
echo "No stable releases found\n";
}
}
?>