crash-report-tools/get-flashhangs.php

734 строки
27 KiB
PHP
Executable File

#!/usr/bin/php
<?php
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
// This script retrieves stats comparing flash versions in hangs and crashes.
// Dates (in YYYY-MM-DD format) given as arguments will be "forcefully" updated.
// *** non-commandline handling ***
if (php_sapi_name() != 'cli') {
// not commandline, assume apache and output own source
header('Content-Type: text/plain; charset=utf8');
print(file_get_contents($_SERVER['SCRIPT_FILENAME']));
exit;
}
include_once('datautils.php');
// *** script settings ***
// turn on error reporting in the script output
ini_set('display_errors', 1);
// make sure new files are set to -rw-r--r-- permissions
umask(022);
// set default time zone - right now, always the one the server is in!
date_default_timezone_set('America/Los_Angeles');
// *** deal with arguments ***
$php_self = array_shift($argv);
$force_dates = array();
if (count($argv)) {
foreach ($argv as $date) {
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $date) &&
date('Y-m-d', strtotime($date)) == $date) {
$force_dates[] = $date;
}
}
}
if (count($force_dates)) {
print('Forcing update for the following dates: '.implode(', ', $force_dates)."\n\n");
}
// *** data gathering variables ***
// reports to gather. fields:
// product - product name
// version - empty is all versions
$reports = array(array('product'=>'Firefox',
'version'=>'4plus',
'version_regex'=>'([4-9]|[0-9][0-9])\..*',
'version_display'=>'4+',
),
array('product'=>'Firefox',
'version'=>'26.0',
'version_regex'=>'26\.0.*',
),
array('product'=>'Firefox',
'version'=>'27.0',
'version_regex'=>'27\.0.*',
),
array('product'=>'Firefox',
'version'=>'28.0',
),
array('product'=>'Firefox',
'version'=>'28.0a2',
),
array('product'=>'Firefox',
'version'=>'29.0a1',
),
array('product'=>'Firefox',
'version'=>'29.0a2',
),
array('product'=>'Firefox',
'version'=>'30.0a1',
),
);
// for how many days back to get the data
$backlog_days = 7;
// *** URLs ***
$on_moz_server = file_exists('/mnt/crashanalysis/rkaiser/');
// File storing the DB access data - including password!
$fdbsecret = '/home/rkaiser/.socorro-prod-dbsecret.json';
if ($on_moz_server) { chdir('/mnt/crashanalysis/rkaiser/'); }
else { chdir('/mnt/mozilla/projects/socorro/'); }
// *** code start ***
// get current day
$curtime = time();
if (file_exists($fdbsecret)) {
$dbsecret = json_decode(file_get_contents($fdbsecret), true);
if (!is_array($dbsecret) || !count($dbsecret)) {
print('ERROR: No DB secrets found, aborting!'."\n");
exit(1);
}
$db_conn = pg_pconnect('host='.$dbsecret['host']
.' port='.$dbsecret['port']
.' dbname=breakpad'
.' user='.$dbsecret['user']
.' password='.$dbsecret['password']);
if (!$db_conn) {
print('ERROR: DB connection failed, aborting!'."\n");
exit(1);
}
// For info on what data can be accessed, see also
// http://socorro.readthedocs.org/en/latest/databasetabledesc.html
// For the DB schema, see
// https://github.com/mozilla/socorro/blob/master/sql/schema.sql
}
else {
// Won't work! (Set just for documenting what fields are in the file.)
$dbsecret = array('host' => 'host.m.c', 'port' => '6432',
'user' => 'analyst', 'password' => 'foo');
print('ERROR: No DB secrets found, aborting!'."\n");
exit(1);
}
foreach ($reports as $rep) {
$channel = array_key_exists('channel', $rep)?$rep['channel']:'';
$ver = array_key_exists('version', $rep)?$rep['version']:'';
$prd = strtolower($rep['product']);
$prdvershort = (($prd == 'firefox')?'ff':(($prd == 'fennec')?'fn':(($prd == 'fennecandroid')?'fna':$prd)))
.(strlen($channel)?'-'.$channel:'')
.(strlen($ver)?'-'.$ver:'');
$prdverfile = $prd
.(strlen($channel)?'.'.$channel:'')
.(strlen($ver)?'.'.$ver:'');
$prdverdisplay = $rep['product']
.(strlen($channel)?' '.ucfirst($channel):'')
.(strlen($ver)?' '.(isset($rep['version_display'])?$rep['version_display']:$ver):'');
$fdfile = $prdvershort.'.flashhang.json';
$fsumpages = 'summarypages.json';
$fwebsum = $prdverfile.'.flashsummary.html';
$fwebdata = $prdverfile.'.flashdata-permajorver.html';
if (file_exists($fdfile)) {
print('Reading stored '.$prdverdisplay.' Flash/hang data'."\n");
$flashdata = json_decode(file_get_contents($fdfile), true);
}
else {
$flashdata = array();
}
$pv_ids = array();
$pv_query =
'SELECT product_version_id '
.'FROM product_versions '
."WHERE product_name = '".$rep['product']."'"
.(strlen($ver)
?' AND release_version '.(isset($rep['version_regex'])
?"~ '^".$rep['version_regex']."$'"
:"= '".$ver."'")
:'')
.(strlen($channel)?" AND build_type = '".ucfirst($channel)."'":'')
.';';
$pv_result = pg_query($db_conn, $pv_query);
if (!$pv_result) {
print('--- ERROR: product version query failed!'."\n");
}
while ($pv_row = pg_fetch_array($pv_result)) {
$pv_ids[] = $pv_row['product_version_id'];
}
if (!count($pv_ids)) {
print('--- ERROR: no versions found in DB for '.$prdverdisplay.'!'."\n");
continue;
}
$throttle_ids = array();
if ($rep['product'] == 'Firefox') {
$throttle_query =
'SELECT product_version_id '
.'FROM product_versions '
."WHERE build_type = 'Release' AND product_name = '".$rep['product']."'"
.(strlen($ver)
?' AND release_version '.(isset($rep['version_regex'])
?"~ '^".$rep['version_regex']."$'"
:"= '".$ver."'")
:'')
.(strlen($channel)?" AND build_type = '".ucfirst($channel)."'":'')
.';';
$throttle_result = pg_query($db_conn, $throttle_query);
if ($throttle_result) {
while ($throttle_row = pg_fetch_array($throttle_result)) {
$throttle_ids[] = $throttle_row['product_version_id'];
}
}
}
$days_to_analyze = array();
for ($daysback = $backlog_days + 1; $daysback > 0; $daysback--) {
$days_to_analyze[] = date('Y-m-d', strtotime(date('Y-m-d', $curtime).' -'.$daysback.' day'));
}
foreach ($force_dates as $anaday) {
if (!in_array($anaday, $days_to_analyze)) {
$days_to_analyze[] = $anaday;
}
}
foreach ($days_to_analyze as $anaday) {
$anadir = $anaday;
print('Flash/hangs: Looking at '.$prdverdisplay.' data for '.$anadir."\n");
if (!file_exists($anadir)) { mkdir($anadir); }
$fpages = 'pages.json';
$fweb = $anadir.'.'.$prdverfile.'.flashhangs.html';
if (!array_key_exists($anadir, $flashdata) || in_array($anadir, $force_dates)) {
print('Fetching Flash/hang data for '.$prdverdisplay."\n");
$rep_query =
'SELECT COUNT(*) as cnt, flash_version, LENGTH(hang_id)>0 as is_hang '
.'FROM reports_clean LEFT JOIN flash_versions'
.' ON (reports_clean.flash_version_id=flash_versions.flash_version_id) '
.'WHERE product_version_id IN ('.implode(',', $pv_ids).') '
." AND utc_day_is(date_processed, '".$anadir."')"
.'GROUP BY flash_version, is_hang '
.'ORDER BY cnt DESC;';
$rep_result = pg_query($db_conn, $rep_query);
if (!$rep_result) {
print('--- ERROR: Flash version query failed!'."\n");
}
$fd = array('total' => array('hang' => 0, 'crash' => 0),
'total_flash' => array('hang' => 0, 'crash' => 0),
'full' => array('hang' => array(), 'crash' => array()),
'main' => array('hang' => array(), 'crash' => array()),
'latest' => array());
while ($rep_row = pg_fetch_array($rep_result)) {
$htype = $rep_row['is_hang']?'hang':'crash';
$fver = preg_match('/^\d/', $rep_row['flash_version'])?$rep_row['flash_version']:'';
if (preg_match('/^(\d+\.\d+)/', $fver, $fvregs)) {
$fvshort = $fvregs[1];
}
else {
$fvshort = $fver;
}
if (array_key_exists($fver, $fd['full'][$htype])) {
$fd['full'][$htype][$fver] += $rep_row['cnt'];
}
else {
$fd['full'][$htype][$fver] = intval($rep_row['cnt']);
}
if (array_key_exists($fvshort, $fd['main'][$htype])) {
$fd['main'][$htype][$fvshort] += $rep_row['cnt'];
}
else {
$fd['main'][$htype][$fvshort] = intval($rep_row['cnt']);
}
$fd['total'][$htype] += $rep_row['cnt'];
if (strlen($fver)) {
$fd['total_flash'][$htype] += $rep_row['cnt'];
if (array_key_exists($fvshort, $fd['latest'])) {
$fvparts = explode('.', $fver);
$flparts = explode('.', $fd['latest'][$fvshort]);
if ((intval(@$fvparts[3]) > intval(@$flparts[3])) ||
((intval(@$fvparts[3]) == intval(@$flparts[3])) &&
(intval(@$fvparts[4]) > intval(@$flparts[4])))) {
$fd['latest'][$fvshort] = $fver;
}
}
else {
$fd['latest'][$fvshort] = $fver;
}
}
}
$adu = getADU(array($anaday), $pv_ids, $throttle_ids, $db_conn);
if (array_key_exists($anaday, $adu)) {
$fd['adu'] = $adu[$anaday];
}
$flashdata[$anadir] = $fd;
ksort($flashdata); // sort by date (key), ascending
file_put_contents($fdfile, json_encode($flashdata));
}
$anafweb = $anadir.'/'.$fweb;
if (!file_exists($anafweb) && $flashdata[$anadir]['total_flash']['hang']) {
// create a per-day HTML page
print('Writing HTML output'."\n");
$doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true; // we want a nice output
$root = $doc->appendChild($doc->createElement('html'));
$head = $root->appendChild($doc->createElement('head'));
$title = $head->appendChild($doc->createElement('title',
$anadir.' '.$prdverdisplay.' Flash Hang Report'));
$style = $head->appendChild($doc->createElement('style'));
$style->setAttribute('type', 'text/css');
$style->appendChild($doc->createCDATASection(
'.pct, .pctdiff {'."\n"
.' text-align: right;'."\n"
.'}'."\n"
.'.pctdiff.hangy {'."\n"
.' color: red;'."\n"
.'}'."\n"
.'.pctdiff.neutral {'."\n"
.' color: gray;'."\n"
.'}'."\n"
.'.pctdiff.crashy {'."\n"
.' color: black;'."\n"
.'}'."\n"
.'.latestver {'."\n"
.' font-weight: bold;'."\n"
.'}'."\n"
));
$body = $root->appendChild($doc->createElement('body'));
$h1 = $body->appendChild($doc->createElement('h1',
$anadir.' '.$prdverdisplay.' Flash Hang Report'));
$fd = $flashdata[$anadir];
// description
$para = $body->appendChild($doc->createElement('p',
'All Flash versions reported in hangs '
.' on '.$prdverdisplay.','
.' compared to how often that Flash version appears in crashes.'));
$para = $body->appendChild($doc->createElement('p',
$fd['total_flash']['hang'].' ('
.sprintf('%.1f', 100 *
$fd['total_flash']['hang'] /
$fd['total']['hang']).'%) '
.' of all hangs and '
.$flashdata[$anadir]['total_flash']['crash'].' ('
.sprintf('%.1f', 100 *
$fd['total_flash']['crash'] /
$fd['total']['crash']).'%) '
.' of all crashes have a Flash version reported, '
.' only those are included in the report.'));
foreach (array('main' => 'Grouped Versions',
'full' => 'Full Versions')
as $fvertype=>$title) {
$h2 = $body->appendChild($doc->createElement('h2', $title));
$table = $body->appendChild($doc->createElement('table'));
$table->setAttribute('border', '1');
// table head
$tr = $table->appendChild($doc->createElement('tr'));
$th = $tr->appendChild($doc->createElement('th', 'Version'));
$th = $tr->appendChild($doc->createElement('th', 'Hangs'));
$th = $tr->appendChild($doc->createElement('th', '+/-'));
$th = $tr->appendChild($doc->createElement('th', 'Crashes'));
foreach ($fd[$fvertype]['hang'] as $fver=>$num) {
if (strlen($fver)) {
$hang_rate = $fd['total_flash']['hang']?
$num / $fd['total_flash']['hang']:0;
$cnum = intval(@$fd[$fvertype]['crash'][$fver]);
$crash_rate = $fd['total_flash']['crash']?
$cnum / $fd['total_flash']['crash']:0;
$tr = $table->appendChild($doc->createElement('tr'));
$td = $tr->appendChild($doc->createElement('td', $fver));
if ($fvertype == 'full') {
if (preg_match('/^(\d+\.\d+)/', $fver, $fvregs)) {
$fvshort = $fvregs[1];
}
else {
$fvshort = $fver;
}
if ($fd['latest'][$fvshort] == $fver) {
$td->setAttribute('class', 'latestver');
}
}
$td = $tr->appendChild($doc->createElement('td',
sprintf('%.1f', 100 * $hang_rate).'%'));
$td->setAttribute('class', 'pct');
$td->setAttribute('title', $num.' hangs');
$td = $tr->appendChild($doc->createElement('td',
sprintf('%+.1f', 100 * ($hang_rate - $crash_rate)).'%'));
$classes = array('pctdiff');
if ($hang_rate > $crash_rate + .02) {
$classes[] = 'hangy';
}
elseif ($hang_rate > $crash_rate - .02) {
$classes[] = 'neutral';
}
else {
$classes[] = 'crashy';
}
$td->setAttribute('class', implode(' ', $classes));
$td = $tr->appendChild($doc->createElement('td',
sprintf('%.1f', 100 * $crash_rate).'%'));
$td->setAttribute('class', 'pct');
$td->setAttribute('title', $cnum.' crashes');
}
}
foreach ($fd[$fvertype]['crash'] as $fver=>$cnum) {
$crash_rate = $fd['total_flash']['crash']?
$cnum / $fd['total_flash']['crash']:0;
if (!intval(@$fd[$fvertype]['hang'][$fver]) && $crash_rate > 0.0005) {
$tr = $table->appendChild($doc->createElement('tr'));
$td = $tr->appendChild($doc->createElement('td', $fver));
$td = $tr->appendChild($doc->createElement('td', '&nbsp;'));
$td = $tr->appendChild($doc->createElement('td', '&nbsp;'));
$td = $tr->appendChild($doc->createElement('td',
sprintf('%.1f', 100 * $crash_rate).'%'));
$td->setAttribute('class', 'pct');
$td->setAttribute('title', $cnum.' crashes');
}
}
}
$doc->saveHTMLFile($anafweb);
// add the page to the pages index
$anafpages = $anadir.'/'.$fpages;
if (file_exists($anafpages)) {
$pages = json_decode(file_get_contents($anafpages), true);
}
else {
$pages = array();
}
$pages[$fweb] =
array('product' => $rep['product'],
'channel' => $channel,
'version' => $ver,
'report' => 'flashhangs',
'report_sub' => null,
'display_ver' => $prdverdisplay,
'display_rep' => 'Flash Hang Report');
file_put_contents($anafpages, json_encode($pages));
}
}
// debug only line
// print_r($flashdata);
if (count($flashdata) &&
(!file_exists($fwebsum) || (filemtime($fwebsum) < filemtime($fdfile)))) {
// create a summary HTML page
print('Writing HTML output'."\n");
$doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true; // we want a nice output
$root = $doc->appendChild($doc->createElement('html'));
$head = $root->appendChild($doc->createElement('head'));
$title = $head->appendChild($doc->createElement('title',
$prdverdisplay.' Flash Summary Report'));
$style = $head->appendChild($doc->createElement('style'));
$style->setAttribute('type', 'text/css');
$style->appendChild($doc->createCDATASection(
'.num, .pct {'."\n"
.' text-align: right;'."\n"
.'}'."\n"
));
$body = $root->appendChild($doc->createElement('body'));
$h1 = $body->appendChild($doc->createElement('h1',
$prdverdisplay.' Flash Summary Report'));
// description
$para = $body->appendChild($doc->createElement('p',
'Daily sums of crash and hang reports on '.$prdverdisplay.','
.' that contain a Flash version, compared to daily total reports.'));
$para = $body->appendChild($doc->createElement('p',
'Columns: Flash hangs and crashes in absolute numbers and % of total'
.' hangs/crashes, sum of both as percentage of total sum of reports.'
.' For hangs, half of all reports are 100% as reports come in pairs.'));
$table = $body->appendChild($doc->createElement('table'));
$table->setAttribute('border', '1');
// table head
$tr = $table->appendChild($doc->createElement('tr'));
$th = $tr->appendChild($doc->createElement('th', 'Date'));
$th->setAttribute('rowspan', '2');
$th = $tr->appendChild($doc->createElement('th', 'Hangs'));
$th->setAttribute('colspan', '3');
$th = $tr->appendChild($doc->createElement('th', 'Crashes'));
$th->setAttribute('colspan', '3');
$th = $tr->appendChild($doc->createElement('th', 'Sum'));
$th->setAttribute('colspan', '2');
$tr = $table->appendChild($doc->createElement('tr'));
$th = $tr->appendChild($doc->createElement('th', 'absoute'));
$th = $tr->appendChild($doc->createElement('th', '% of hangs'));
$th = $tr->appendChild($doc->createElement('th', 'rate'));
$th = $tr->appendChild($doc->createElement('th', 'absolute'));
$th = $tr->appendChild($doc->createElement('th', '% of crashes'));
$th = $tr->appendChild($doc->createElement('th', 'rate'));
$th = $tr->appendChild($doc->createElement('th', '% of total'));
$th = $tr->appendChild($doc->createElement('th', 'rate'));
$lastdate = null;
foreach (array_reverse($flashdata) as $date=>$fd) {
if (is_null($lastdate) || ($date > $lastdate)) { $lastdate = $date; }
$adu = intval(@$fd['adu']);
if (!$adu) {
// We should only get here to backfill on old data.
$adus = getADU(array($date), $pv_ids, $throttle_ids, $db_conn);
if (array_key_exists($date, $adus)) {
$adu = $adus[$date];
// Put it in $flashdata and save it.
$flashdata[$date]['adu'] = $adu;
file_put_contents($fdfile, json_encode($flashdata));
}
}
$total_hang_pairs = ($date < '2012-11-16')?($fd['total']['hang'] / 2)
:$fd['total']['hang'];
$hang_pct = $fd['total']['hang']
? $fd['total_flash']['hang'] / $total_hang_pairs
: 0;
$hang_rate = $adu ? $fd['total_flash']['hang'] * 100 / $adu : 0;
$crash_pct = $fd['total']['crash']
? $fd['total_flash']['crash'] / $fd['total']['crash']
: 0;
$crash_rate = $adu ? $fd['total_flash']['crash'] * 100 / $adu : 0;
$total_pct = $fd['total']['crash'] + $total_hang_pairs
? ($fd['total_flash']['crash'] + $fd['total_flash']['hang'])
/ ($fd['total']['crash'] + $total_hang_pairs)
: 0;
$total_rate = $adu
?($fd['total_flash']['crash'] + $fd['total_flash']['hang'])
* 100 / $adu
: 0;
if ($total_rate) {
$tr = $table->appendChild($doc->createElement('tr'));
$td = $tr->appendChild($doc->createElement('td', $date));
$td = $tr->appendChild($doc->createElement('td',
$fd['total_flash']['hang']));
$td->setAttribute('class', 'num');
$td = $tr->appendChild($doc->createElement('td',
sprintf('%.1f', 100 * $hang_pct).'%'));
$td->setAttribute('class', 'pct');
$td = $tr->appendChild($doc->createElement('td',
sprintf('%.2f', $hang_rate)));
$td->setAttribute('class', 'num');
$td = $tr->appendChild($doc->createElement('td',
$fd['total_flash']['crash']));
$td->setAttribute('class', 'num');
$td = $tr->appendChild($doc->createElement('td',
sprintf('%.1f', 100 * $crash_pct).'%'));
$td->setAttribute('class', 'pct');
$td = $tr->appendChild($doc->createElement('td',
sprintf('%.2f', $crash_rate)));
$td->setAttribute('class', 'num');
$td = $tr->appendChild($doc->createElement('td',
sprintf('%.1f', 100 * $total_pct).'%'));
$td->setAttribute('class', 'pct');
$td = $tr->appendChild($doc->createElement('td',
sprintf('%.2f', $total_rate)));
$td->setAttribute('class', 'num');
}
}
$doc->saveHTMLFile($fwebsum);
// add the page to the summary pages index
if (file_exists($fsumpages)) {
$sumpages = json_decode(file_get_contents($fsumpages), true);
}
else {
$sumpages = array();
}
$sumpages[$fwebsum] =
array('product' => $rep['product'],
'channel' => $channel,
'version' => $ver,
'report' => 'flashsummary',
'report_sub' => null,
'last_date' => $lastdate,
'display_ver' => $prdverdisplay,
'display_rep' => 'Flash Summary Report');
file_put_contents($fsumpages, json_encode($sumpages));
}
if (($ver == '4plus') && count($flashdata) &&
(!file_exists($fwebdata) || (filemtime($fwebdata) < filemtime($fdfile)))) {
// create an HTML summary data page
print('Writing HTML output'."\n");
$doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true; // we want a nice output
$root = $doc->appendChild($doc->createElement('html'));
$head = $root->appendChild($doc->createElement('head'));
$title = $head->appendChild($doc->createElement('title',
$prdverdisplay.' Flash Main Version Data'));
$style = $head->appendChild($doc->createElement('style'));
$style->setAttribute('type', 'text/css');
$style->appendChild($doc->createCDATASection(
'.num, .pct {'."\n"
.' text-align: right;'."\n"
.'}'."\n"
));
$body = $root->appendChild($doc->createElement('body'));
$h1 = $body->appendChild($doc->createElement('h1',
$prdverdisplay.' Flash Main Version Data'));
// description
$para = $body->appendChild($doc->createElement('p',
'Daily data of crash and hang reports on '.$prdverdisplay.','
.' that contain a Flash version, grouped by main Flash versions.'));
$para = $body->appendChild($doc->createElement('p',
'The percentage values are shares of the total Flash hangs or crashes'
.' reported for that day. Actual counts appear in tooltips.'));
$allmajors = array();
foreach (array_reverse($flashdata) as $date=>$fd) {
foreach (array('hang', 'crash') as $reptype) {
foreach ($fd['main'][$reptype] as $fver=>$num) {
if (preg_match('/^(\d+)\.(\d+)$/', $fver, $regs) &&
($regs[1] > 5) && ($regs[1] < 20) &&
!in_array($fver, $allmajors)) {
$allmajors[] = $fver;
}
}
}
}
// Sort main Flash versions
sort($allmajors);
foreach (array('crash' => 'Crashes', 'hang' => 'Hangs') as $reptype=>$title) {
$h2 = $body->appendChild($doc->createElement('h2', $title));
$table = $body->appendChild($doc->createElement('table'));
$table->setAttribute('border', '1');
// table head
$tr = $table->appendChild($doc->createElement('tr'));
$th = $tr->appendChild($doc->createElement('th', 'Date'));
$th->setAttribute('rowspan', '2');
$th = $tr->appendChild($doc->createElement('th', 'Main Flash Version'));
$th->setAttribute('colspan', count($allmajors));
$tr = $table->appendChild($doc->createElement('tr'));
foreach ($allmajors as $fver) {
$th = $tr->appendChild($doc->createElement('th', $fver));
}
$lastdate = null;
foreach (array_reverse($flashdata) as $date=>$fd) {
if (is_null($lastdate) || ($date > $lastdate)) { $lastdate = $date; }
$data_by_major = array();
foreach ($allmajors as $fver) {
$data_by_major[$fver] = array(
'count' => intval(@$fd['main'][$reptype][$fver]),
'pct' => $fd['total_flash'][$reptype]
? intval(@$fd['main'][$reptype][$fver]) / $fd['total_flash'][$reptype]
: 0);
}
$tr = $table->appendChild($doc->createElement('tr'));
$td = $tr->appendChild($doc->createElement('td', $date));
foreach ($data_by_major as $fver=>$fvdata) {
$td = $tr->appendChild($doc->createElement('td',
sprintf('%.2f', 100 * $fvdata['pct']).'%'));
$td->setAttribute('class', 'pct');
$td->setAttribute('title', $fvdata['count']);
}
}
}
$doc->saveHTMLFile($fwebdata);
// add the page to the summary pages index
if (file_exists($fsumpages)) {
$sumpages = json_decode(file_get_contents($fsumpages), true);
}
else {
$sumpages = array();
}
$sumpages[$fwebdata] =
array('product' => $rep['product'],
'channel' => $channel,
'version' => $ver,
'report' => 'flashmajorverdata',
'report_sub' => null,
'last_date' => $lastdate,
'display_ver' => $prdverdisplay,
'display_rep' => 'Flash Main Version Data');
file_put_contents($fsumpages, json_encode($sumpages));
}
print("\n");
}
// *** helper functions ***
function getADU($days, $pv_ids, $throttle_ids, $db_conn) {
if (!count($days)) { return array(); }
$adu = array();
$adu_query =
'SELECT SUM('.(count($throttle_ids)?'CASE
WHEN product_version_id IN ('.implode(',', $throttle_ids).')
THEN adu_count / 10 ELSE adu_count END':'adu_count').') as adu,
adu_date '
.'FROM product_adu '
.'WHERE product_version_id IN ('.implode(',', $pv_ids).') '
.' AND '
.((count($days) > 1) ? " adu_date IN ('".implode("','", $days)."') "
: " adu_date = '".$days[0]."' ")
.'GROUP BY adu_date;';
$adu_result = pg_query($db_conn, $adu_query);
if (!$adu_result) {
print('--- ERROR: ADU query failed!'."\n");
}
while ($adu_row = pg_fetch_array($adu_result)) {
$adu[$adu_row['adu_date']] = intval($adu_row['adu']);
}
return $adu;
}
?>