Create helper to shorten signatures and create links to the repository
authorVincent Tondellier <tonton+hg@team1664.org>
Wed, 02 May 2012 21:46:30 +0200
changeset 3 2ff78fe4abda
parent 2 873ceb7769a8
child 4 7ffe7b48b8de
Create helper to shorten signatures and create links to the repository browser.
CrashTest.conf
CrashTest.pl
public/assets/js/application.js
templates/layouts/main.html.ep
templates/report/backtrace/frames.html.ep
--- 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