Report parser complete

This commit is contained in:
Latif Khalifa
2013-10-04 03:47:59 +02:00
parent 483c845a27
commit a7d294b3c0
5 changed files with 318 additions and 2 deletions

58
htdocs/batch_process.php Normal file
View File

@@ -0,0 +1,58 @@
<?php
define("SITE_ROOT", realpath(dirname(__file__)));
require_once SITE_ROOT . "/lib/init.php";
set_time_limit(0);
if (PHP_SAPI != "cli")
{
header("Content-Type: text/plain");
}
function rrmdir($dir)
{
foreach(glob($dir . '/*') as $file)
{
if(is_dir($file))
rrmdir($file);
else
unlink($file);
}
rmdir($dir);
}
$reports = ReportParser::getUnprocessedIDs();
print "Working dir set to " . ReportParser::getWorkPath() . "\n";
mkdir(ReportParser::getWorkPath());
chdir(ReportParser::getWorkPath());
foreach($reports as $id)
{
print "Processing report {$id} \n";
$r = ReportParser::parse($id);
$miniDump = $r["Minidump"];
if (!$miniDump || !($miniDump->getData()))
{
ReportParser::setProcessed($id, 1);
continue;
}
if (!($version = $r["clientVersion"])|| !($chan = $r["clientChannel"]))
{
ReportParser::setProcessed($id, 1);
continue;
}
$stacktrace = ReportParser::getStackTrace("$chan-$version", $r["Minidump"]);
$crash = new CrashReport();
$crash->init($id, $r, $stacktrace);
if ($crash->save())
{
ReportParser::setProcessed($id, 1);
}
}
rrmdir(ReportParser::getWorkPath());

157
htdocs/lib/CrashReport.php Normal file
View File

@@ -0,0 +1,157 @@
<?php
class CrashReport
{
public $id;
public $reported;
public $client_version;
public $client_channel;
public $os;
public $os_type;
public $os_version;
public $cpu;
public $gpu;
public $opengl_version;
public $ram;
public $grid;
public $region;
public $crash_reason;
public $crash_address;
public $crash_thread;
public $modules = array();
public $threads = array();
public $raw_stacktrace;
function delete()
{
global $DB;
$DB->query(kl_str_sql("delete from reports where id=!i", $this->id));
}
function save()
{
global $DB;
$this->delete();
$q = kl_str_sql("insert into reports (
id,
reported,
client_version,
client_channel,
os,
os_type,
os_version,
cpu,
gpu,
opengl_version,
ram,
grid,
region,
crash_reason,
crash_address,
crash_thread,
raw_stacktrace
) values (!i, !t, !s, !s, !s, !s, !s, !s, !s, !s, !i, !s, !s, !s, !s, !i, !s)",
$this->id,
$this->reported,
$this->client_version,
$this->client_channel,
$this->os,
$this->os_type,
$this->os_version,
$this->cpu,
$this->gpu,
$this->opengl_version,
$this->ram,
$this->grid,
$this->region,
$this->crash_reason,
$this->crash_address,
$this->crash_thread,
$this->raw_stacktrace);
if ($res = $DB->query($q))
{
return true;
}
else
{
return false;
}
}
function parseStackTrace($stacktrace)
{
$lines = explode("\n", $stacktrace);
foreach($lines as $line)
{
$elems = explode("|", $line);
$type = $elems[0];
switch ($type)
{
case "OS":
$this->os_type = $elems[1];
$this->os_version = $elems[2];
break;
case "Crash":
$this->crash_reason = $elems[1];
$this->crash_address = $elems[2];
$this->crash_thread = (int)$elems[3];
break;
case "Module":
$m = new stdClass;
$m->name = $elems[1];
$m->version = $elems[2];
$this->modules[] = $m;
break;
default:
if (false !== filter_var($type, FILTER_VALIDATE_INT))
{
$threadID = (int)$type;
if (!isset($this->threads[$threadID]))
{
$t = new stdClass;
$t->frames = array();
}
else
{
$t = $this->threads[$threadID];
}
$frameID = (int)$elems[1];
$frame = new stdClass;
$frame->module = $elems{2};
$frame->function = $elems[3];
$frame->source_file = $elems[4];
$frame->source_line = $elems[5];
$frame->function_offset = $elems[6];
$t->frames[$frameID] = $frame;
$this->threads[$threadID] = $t;
}
}
}
}
function init($id, $data, $stacktrace)
{
$this->id = $id;
$this->reported = $data["reported"];
$this->client_version = $data["clientVersion"];
$this->client_channel = $data["clientChannel"];
$this->os = $data["DebugLog"]["OSInfo"];
$this->gpu = $data["DebugLog"]["GraphicsCard"];
$this->cpu = $data["DebugLog"]["CPUInfo"]["CPUString"];
$this->opengl_version = $data["DebugLog"]["GLInfo"]["GLVersion"];
$this->ram = $data["DebugLog"]["RAMInfo"]["Allocated"];
$this->grid = $data["DebugLog"]["GridName"];
$this->region = $data["DebugLog"]["CurrentRegion"];
unset($data["Minidump"]);
$this->raw_stacktrace = $stacktrace;
$this->parseStackTrace($this->raw_stacktrace);
}
}

View File

@@ -14,6 +14,7 @@ class DBH
function log($line)
{
return;
static $f = false;
static $failed = false;

View File

@@ -33,18 +33,96 @@ require_once SITE_ROOT.'/lib/llsd_decode.php';
class ReportParser
{
static $extracted = array();
function parse($id)
{
global $DB;
$q = kl_str_sql("select * from raw_reports where report_id=!i", $id);
if (!$res = $DB->query($q) OR !$row = $DB->fetchRow($res))
{
return;
return new stdClass;
}
$data = new stdClass;
$DB->loadFromDbRow($data, $res, $row);
$data->report = llsd_decode($data->raw_data);
$data->report["reported"] = $data->reported;
unset($data->raw_data);
return $data;
if ($client = $data->report["DebugLog"]["ClientInfo"])
{
//var_dump($client);
$data->report["clientVersion"] = $client["MajorVersion"] . "." . $client["MinorVersion"] . "." . $client["PatchVersion"] . "." .$client["BuildVersion"];
$data->report["clientChannel"] = str_replace(" ", "", $client["Name"]);
}
// $data->report["raw"] = $row;
return $data->report;
}
function setProcessed($id, $status)
{
global $DB;
$ret = array();
$q = kl_str_sql("update raw_reports set processed=!i where report_id=!i", $status, $id);
if ($res = $DB->query($q))
{
return true;
}
else
{
return false;
}
}
function getUnprocessedIDs()
{
global $DB;
$ret = array();
$q = kl_str_sql("select report_id from raw_reports where processed=!i", 0);
if (!$res = $DB->query($q))
{
return $ret;
}
while ($row = $DB->fetchRow($res))
{
$ret[] = (int)$row["report_id"];
}
return $ret;
}
function getWorkPath()
{
static $p = "";
if ($p) return $p;
return $p = sys_get_temp_dir() . "/extract-syms-" . (string)getmypid();
}
function getStackTrace($prefix, $dump)
{
if (!$dump || !($data = $dump->getData())) return;
file_put_contents(self::getWorkPath() . "/working.dmp", $data);
$match = SITE_ROOT . "/../incoming_symbols/$prefix-symbols-*.tar.bz2";
foreach(glob($match) as $file)
{
if (!in_array($file, self::$extracted))
{
self::$extracted[] = $file;
print "Unpacking $file\n";
shell_exec("tar xjf " . escapeshellcmd($file));
}
}
$cmd = "minidump_stackwalk -m " . self::getWorkPath() . "/working.dmp " . self::getWorkPath();
print "Executing: $cmd\n";
return shell_exec($cmd);
}
}

View File

@@ -1,3 +1,4 @@
drop table if exists reports;
drop table if exists raw_reports;
drop table if exists users;
drop table if exists options;
@@ -31,4 +32,25 @@ create table raw_reports(
reported timestamp not null default current_timestamp,
processed integer not null default 0,
raw_data longtext
);
create table reports(
id integer not null primary key,
reported timestamp,
client_version varchar(32),
client_channel varchar(32),
os varchar(128),
os_type varchar(32),
os_version varchar(128),
cpu varchar(128),
gpu varchar(128),
opengl_version varchar(128),
gpu_driver varchar(128),
ram integer,
grid varchar(128),
region varchar(128),
crash_reason varchar(128),
crash_address varchar(16),
crash_thread integer,
raw_stacktrace text
);