Create helper to shorten signatures and create links to the repository
browser.
--- a/CrashTest.conf Wed May 02 21:43:53 2012 +0200
+++ b/CrashTest.conf Wed May 02 21:46:30 2012 +0200
@@ -1,5 +1,8 @@
{
DataDir => 'data/',
MinidumpStackwalkJSON => './stackwalker',
- SymbolsPath => '',
+ SymbolsPath => 'breakpad-debug-symbols/*',
+ ScmLinks => {
+ "svn:svn.example.org/testproject" => 'https://redmine.example.org/projects/testproject/repository/entry/<%= $scmpath =%>?rev=<%= $rev =%>#L<%= $line =%>',
+ },
};
--- a/CrashTest.pl Wed May 02 21:43:53 2012 +0200
+++ b/CrashTest.pl Wed May 02 21:46:30 2012 +0200
@@ -3,11 +3,53 @@
use Mojolicious::Lite;
use UUID;
use Mojo::JSON;
+use Mojo::UserAgent;
my @valid_params = qw/Add-ons Distributor ProductName ReleaseChannel StartupTime UserID Version BuildID CrashTime Comments/;
my $config = plugin 'Config';
my $data_path = $config->{DataDir};
+
+helper scm_file_link => sub {
+ my ($self, $file, $line) = @_;
+
+ return "" unless(defined($file));
+
+ if($file =~ qr{([a-z]+):([a-z/.]+):(.+):(\d+)})
+ {
+ my ($scm, $repo, $scmpath, $rev) = ($1, $2, $3, $4);
+ my $filename = File::Spec->splitpath($scmpath);
+ my $scmrepo = "$scm:$repo";
+ if(exists($config->{ScmLinks}->{$scmrepo})) {
+ return Mojo::ByteStream->new($self->link_to("$filename:$line" =>
+ $self->render(inline => $config->{ScmLinks}->{$scmrepo}, repo => $repo, scmpath => $scmpath, rev => $rev, line => $line, partial => 1)
+ ));
+ }
+ #return $file;
+ }
+ my $filebase = (File::Spec->splitpath($file))[-1];
+ if(defined($line) && $line ne "") {
+ return "$filebase:$line";
+ }
+ return $filebase;
+};
+
+helper shorten_signature => sub {
+ my ($self, $signature) = @_;
+
+ return "" if(!defined($signature) || $signature eq "");
+
+ my $short_signature = $signature;
+ if($signature =~ qr{([^<]+)<.+>::([^()]+)\(.*\)(.*)}) {
+ # c++ with template
+ $short_signature = "$1<>::$2()$3";
+ } elsif($signature =~ qr{([^()]+)\(.*\)(.*)}) {
+ # c/c++
+ $short_signature = "$1()$2";
+ }
+ return Mojo::ByteStream->new($self->t(span => (title => $signature, class => "shortened-signature") => $short_signature));
+};
+
# Upload form in DATA section
get '/' => sub {
my $self = shift;
@@ -15,11 +57,13 @@
my @files;
opendir my ($dh), $data_path;
while(readdir $dh) {
- if($_ =~ /(.*)\.pjson$/) {
+ if($_ =~ /(.*)\.json$/) {
my $filename = File::Spec->catfile($data_path, $_);
push @files, {
file => $filename,
uuid => $1,
+ signature => $1,
+ product => "",
date => (stat $filename)[9],
};
}
@@ -37,43 +81,47 @@
get '/report/:uuid' => [ uuid => qr/[0-9a-fA-F-]+/ ] => sub {
my $self = shift;
- open JSON, '<', $data_path . '/' . $self->param('uuid') . '.pjson';
+ open JSON, '<', File::Spec->catfile($data_path, $self->param('uuid') . '.json') or die $!;
my @json_content_lines = <JSON>;
my $json_content = join('', @json_content_lines);
+ close JSON;
+
my $json = Mojo::JSON->new;
my $processed_data = $json->decode($json_content);
- close JSON;
$self->stash(processed_data => $processed_data);
$self->render('report/crash');
} => 'report';
-# Streaming multipart upload (invoked twice, due to early "request" event)
post '/submit' => sub {
my $self = shift;
-
+
# save the dump in a file
my $file = $self->req->upload('upload_file_minidump');
my ($uuid, $uuidstr);
UUID::generate($uuid);
UUID::unparse($uuid, $uuidstr);
- $file->move_to($data_path . '/' . $uuidstr . '.dmp');
+ my $dmp_file = File::Spec->catfile($data_path, "$uuidstr.dmp");
+ $file->move_to($dmp_file);
# Create json for the params
- #my @par = $self->req->param;
my %paramshash = map { $_ => $self->req->param($_) } $self->req->param;
+ my $out = qx($config->{MinidumpStackwalkJSON} "$dmp_file" $config->{SymbolsPath} 2>/dev/null) or die $!;
+
my $json = Mojo::JSON->new;
- my $j = $json->encode(\%paramshash);
- open JSON, '>', $data_path . '/' . $uuidstr . '.json' or die $!;
+ my $pjson = $json->decode($out);
+ $pjson->{client_info} = \%paramshash;
+
+ my $j = $json->encode($pjson);
+ open JSON, '>', File::Spec->catfile($data_path, "$uuidstr.json") or die $!;
print JSON $j;
close JSON;
- system($config->{MinidumpStackwalkJSON} . " " . $data_path . '/' . $uuidstr . '.dmp' . " " . $config->{SymbolsPath} . " > " . $data_path . '/' . $uuidstr . '.pjson' . " 2>/dev/null");
-
# reply
- $self->render_text($j);
+ $self->render_text($pjson->{status});
};
+app->secret('My secret passphrase here');
app->start;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/public/assets/js/application.js Wed May 02 21:46:30 2012 +0200
@@ -0,0 +1,11 @@
+$(document).ready(function () {
+ $('.signature-column').append(' <a class="expand" href="#">[Expand]</a>');
+ $('.expand').click(function () {
+ // swap cell title into cell text for each cell in this column
+ $(".shortened-signature", $(this).parents('table')).each(function () {
+ $(this).text($(this).attr('title')).removeAttr('title');
+ });
+ $(this).remove();
+ return false;
+ });
+});
--- a/templates/layouts/main.html.ep Wed May 02 21:43:53 2012 +0200
+++ b/templates/layouts/main.html.ep Wed May 02 21:46:30 2012 +0200
@@ -12,13 +12,6 @@
padding-top: 60px;
}
% end
- % if ( $self->app->mode eq 'development'){
- %= javascript '/assets/js/jquery.js'
- %= javascript '/assets/js/bootstrap.js'
- %} else {
- %= javascript '/assets/js/jquery-min.js'
- %= javascript '/assets/js/bootstrap-min.js'
- %}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
@@ -88,5 +81,13 @@
<%= content %>
</div>
+ % if ( $self->app->mode eq 'development'){
+ %= javascript '/assets/js/jquery.js'
+ %= javascript '/assets/js/bootstrap.js'
+ %} else {
+ %= javascript '/assets/js/jquery.min.js'
+ %= javascript '/assets/js/bootstrap.min.js'
+ %}
+ %= javascript '/assets/js/application.js'
</body>
</html>
--- a/templates/report/backtrace/frames.html.ep Wed May 02 21:43:53 2012 +0200
+++ b/templates/report/backtrace/frames.html.ep Wed May 02 21:46:30 2012 +0200
@@ -3,7 +3,7 @@
<tr>
<th>Frame</th>
<th>Module</th>
- <th>Signature</th>
+ <th class="signature-column">Signature</th>
<th>Source</th>
</tr>
</thead>
@@ -11,8 +11,8 @@
<tr>
%= t td => $frame->{frame}
%= t td => $frame->{module}
- %= t td => $frame->{function}
- %= t td => (File::Spec->splitpath($frame->{file}))[-1]
+ <td><%= shorten_signature $frame->{function} =%></td>
+ <td><%= scm_file_link($frame->{file}, $frame->{line}) =%></td>
</tr>
% }
% end