[bugzilla-gnome-org-extensions] Add support for "similar traces" and "identical traces".
- From: Krzesimir Nowak <krnowak src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [bugzilla-gnome-org-extensions] Add support for "similar traces" and "identical traces".
- Date: Thu, 20 Nov 2014 22:12:40 +0000 (UTC)
commit 51cfaccf9fcc26d9c21f89518d2ba2e128466d51
Author: Max Kanat-Alexander <mkanat everythingsolved com>
Date: Wed Aug 5 05:32:50 2009 -0500
Add support for "similar traces" and "identical traces".
code/db_schema-abstract_schema.pl | 4 +-
lib/TraceParser/Hooks.pm | 22 ++++++++++--
lib/TraceParser/Trace.pm | 51 ++++++++++++++++++----------
template/en/default/pages/trace.html.tmpl | 28 +++++++++++++++
template/en/default/trace/format.html.tmpl | 9 ++++-
web/style.css | 6 ++--
6 files changed, 92 insertions(+), 28 deletions(-)
---
diff --git a/code/db_schema-abstract_schema.pl b/code/db_schema-abstract_schema.pl
index db7112a..fd3a04d 100644
--- a/code/db_schema-abstract_schema.pl
+++ b/code/db_schema-abstract_schema.pl
@@ -34,8 +34,8 @@ $schema->{trace} = {
COLUMN => 'comment_id',
DELETE => 'CASCADE'}},
type => {TYPE => 'varchar(255)', NOTNULL => 1},
- short_hash => {TYPE => 'char(22)', NOTNULL => 1},
- stack_hash => {TYPE => 'char(22)', NOTNULL => 1},
+ short_hash => {TYPE => 'char(22)'},
+ stack_hash => {TYPE => 'char(22)'},
trace_hash => {TYPE => 'char(22)', NOTNULL => 1},
trace_text => {TYPE => 'LONGTEXT', NOTNULL => 1},
quality => {TYPE => 'real', NOTNULL => 1},
diff --git a/lib/TraceParser/Hooks.pm b/lib/TraceParser/Hooks.pm
index 306511b..46928a5 100644
--- a/lib/TraceParser/Hooks.pm
+++ b/lib/TraceParser/Hooks.pm
@@ -38,14 +38,14 @@ sub install_update_db {
return if $has_traces;
print "Parsing traces from comments...\n";
- my $total = $dbh->selectrow_array('SELECT COUNT(*) FROM longdescs');
+ my $total = 75000; #$dbh->selectrow_array('SELECT COUNT(*) FROM longdescs');
if ($dbh->isa('Bugzilla::DB::Mysql')) {
$dbh->{'mysql_use_result'} = 1;
}
my $sth = $dbh->prepare('SELECT comment_id, thetext FROM longdescs
- ORDER BY comment_id');
+ ORDER BY comment_id DESC LIMIT 75000');
$sth->execute();
my $count = 1;
my @traces;
@@ -93,7 +93,7 @@ sub format_comment {
}
else {
my $stacktrace = TraceParser::Trace->stacktrace_from_text($$text);
- $trace->{stacktrace_object} = $stacktrace;
+ $trace->{stack} = $stacktrace;
$match_text = $stacktrace->text;
}
@@ -114,6 +114,22 @@ sub page {
return if $page !~ '^trace\.';
my $trace_id = Bugzilla->cgi->param('trace_id');
my $trace = TraceParser::Trace->check({ id => $trace_id });
+ $trace->bug->check_is_visible;
+
+ if ($trace->stack_hash) {
+ my $identical_traces = TraceParser::Trace->match(
+ { stack_hash => $trace->stack_hash });
+ my $similar_traces = TraceParser::Trace->match(
+ { short_hash => $trace->short_hash });
+ # Remove identical traces.
+ my %identical = map { $_->id => 1 } @$identical_traces;
+ @$similar_traces = grep { !$identical{$_->id} } @$similar_traces;
+ # Remove this trace from the identical traces.
+ @$identical_traces = grep { $_->id != $trace->id } @$identical_traces;
+ $vars->{similar_traces} = $similar_traces;
+ $vars->{identical_traces} = $identical_traces;
+ }
+
$vars->{trace} = $trace;
}
diff --git a/lib/TraceParser/Trace.pm b/lib/TraceParser/Trace.pm
index 3a910ac..b0f3ddf 100644
--- a/lib/TraceParser/Trace.pm
+++ b/lib/TraceParser/Trace.pm
@@ -55,13 +55,10 @@ use constant VALIDATORS => {
trace_hash => \&_check_hash,
trace_text => \&_check_thetext,
type => \&_check_type,
- quality => \&_check_quality,
};
use constant REQUIRED_CREATE_FIELDS => qw(
comment_id
- short_hash
- stack_hash
trace_hash
trace_text
type
@@ -70,10 +67,14 @@ use constant REQUIRED_CREATE_FIELDS => qw(
# This is how long a Base64 MD5 Hash is.
use constant HASH_SIZE => 22;
+# How many functions we should be hashing for the short_hash.
+use constant STACK_SIZE => 5;
+
use constant TRACE_TYPES => ['GDB', 'Python'];
use constant IGNORE_FUNCTIONS => qw(
__kernel_vsyscall
+ __libc_start_main
raise
abort
??
@@ -95,26 +96,42 @@ sub parse_from_text {
my $trace = $class->stacktrace_from_text($text);
return undef if !$trace;
+ my $crash_thread = $trace->thread_with_crash || $trace->threads->[0];
+ my @frames = @{ $crash_thread->frames };
+ my ($has_crash) = grep { $_->is_crash } @frames;
+
my @all_functions;
my $quality = 0;
- my $crash_thread = $trace->thread_with_crash || $trace->threads->[0];
- foreach my $frame (@{ $crash_thread->frames }) {
+ my $counting_functions = 0;
+ foreach my $frame (@frames) {
+ if (!$has_crash or $frame->number > $has_crash->number) {
+ $counting_functions++;
+ }
+ next if !$counting_functions;
+
foreach my $item (qw(args number file line code)) {
$quality++ if defined $frame->$item && $frame->$item ne '';
}
+
my $function = $frame->function;
if (!grep($_ eq $function, IGNORE_FUNCTIONS)) {
- push(@all_functions, $frame->function);
+ $function =~ s/^IA__//;
+ push(@all_functions, $function);
$quality++;
}
}
- $quality = $quality / scalar(@{ $crash_thread->frames });
+ $quality = "$quality.0" / scalar(@frames);
- my $max_short_stack = $#all_functions > 4 ? 4 : $#all_functions;
- my @short_stack = @all_functions[0..$max_short_stack];
- my $stack_hash = md5_base64(join(',', @all_functions));
- my $short_hash = md5_base64(join(',', @short_stack));
+ my $stack_hash;
+ my $short_hash;
+ if (@all_functions) {
+ my $max_short_stack = $#all_functions >= STACK_SIZE ? STACK_SIZE
+ : $#all_functions;
+ my @short_stack = @all_functions[0..($max_short_stack-1)];
+ $stack_hash = md5_base64(join(',', @all_functions));
+ $short_hash = md5_base64(join(',', @short_stack));
+ }
my $trace_text = $trace->text;
my $trace_hash = md5_base64($trace_text);
@@ -133,7 +150,7 @@ sub parse_from_text {
###############################
sub comment_id { return $_[0]->{comment_id}; }
-sub full_hash { return $_[0]->{full_hash}; }
+sub stack_hash { return $_[0]->{stack_hash}; }
sub short_hash { return $_[0]->{short_hash}; }
sub trace_hash { return $_[0]->{trace_hash}; }
sub text { return $_[0]->{trace_text}; }
@@ -150,12 +167,12 @@ sub bug {
return $self->{bug};
}
-sub stacktrace_object {
+sub stack {
my $self = shift;
my $type = $self->type;
eval("use $type; 1;") or die $@;
- $self->{stacktrace_object} ||= $type->parse({ text => $self->trace_text });
- return $self->{stacktrace_object};
+ $self->{stack} ||= $type->parse({ text => $self->trace_text });
+ return $self->{stack};
}
###############################
@@ -165,7 +182,7 @@ sub stacktrace_object {
sub _check_hash {
my ($self, $hash) = @_;
$hash = trim($hash);
- ThrowCodeError('traceparser_no_hash') if !$hash;
+ return undef if !$hash;
length($hash) == HASH_SIZE
or ThrowCodeError('traceparser_bad_hash', { hash => $hash });
return $hash;
@@ -194,6 +211,4 @@ sub _check_type {
return $type;
}
-sub _check_quality { return int($_[1]); }
-
1;
diff --git a/template/en/default/pages/trace.html.tmpl b/template/en/default/pages/trace.html.tmpl
index 68472c1..efb56b1 100644
--- a/template/en/default/pages/trace.html.tmpl
+++ b/template/en/default/pages/trace.html.tmpl
@@ -23,8 +23,36 @@
title = "Trace $trace.id From Bug $trace.bug.id"
%]
+[% IF identical_traces.size %]
+ <p>Identical Traces:</p>
+ [% PROCESS trace_list list = identical_traces %]
+[% END %]
+
+[% IF similar_traces.size %]
+ <p>Similar Traces:</p>
+ [% PROCESS trace_list list = similar_traces %]
+[% END %]
+
<table border="0" cellpadding="0" cellspacing="0"><tr><td><div class="trace">
<pre>[% trace.text FILTER html %]
</pre></div></td></tr></table>
[% PROCESS global/footer.html.tmpl %]
+
+[% BLOCK trace_list %]
+ <ul class="trace_list">
+ [% FOREACH this_trace = list %]
+ [% SET bug = this_trace.bug %]
+ <li>
+ <a href="page.cgi?id=trace.html&trace_id=
+ [%- this_trace.id FILTER url_quote %]">Trace
+ [% this_trace.id FILTER html %]</a> on
+ [%+ "Bug $bug.id" FILTER bug_link(bug.id) %]
+ (Quality: [% this_trace.quality FILTER html %])
+ [% IF user.can_see_bug(bug) %]
+ [%+ bug.product FILTER html %]
+ [% END %]
+ </li>
+ [% END %]
+ </ul>
+[% END %]
diff --git a/template/en/default/trace/format.html.tmpl b/template/en/default/trace/format.html.tmpl
index 7af617e..4f39dd6 100644
--- a/template/en/default/trace/format.html.tmpl
+++ b/template/en/default/trace/format.html.tmpl
@@ -27,9 +27,8 @@
<table border="0" cellpadding="0" cellspacing="0"><tr><td>
<div class="trace">
[% IF trace.type.match('Python') %]
- PYTHON TRACE
[% ELSE %]
- [% SET st = trace.stacktrace_object %]
+ [% SET st = trace.stack %]
[% IF st.thread_with_crash %]
[% threads = [st.thread_with_crash] %]
[% ELSE %]
@@ -49,6 +48,12 @@
<span class="frame_number">#[% frame.number FILTER html %]</span>
[% END %]
<span class="frame_function">[% frame.function FILTER html %]</span>
+ [% IF frame.library %]
+ <div class="frame_library_container">
+ from
+ <span class="frame_library">[% frame.library FILTER html %]</span>
+ </div>
+ [% END %]
[% IF frame.file %]
<div class="frame_file_container">
at <span class="frame_file">[% frame.file FILTER html %]</span>
diff --git a/web/style.css b/web/style.css
index 6b313f0..cf193d9 100644
--- a/web/style.css
+++ b/web/style.css
@@ -31,11 +31,11 @@
color: #4e9a06;
}
-.frame_file_container {
- margin-left: 3em;
+.frame_file_container, .frame_library_container {
+ margin-left: 2em;
}
-.frame_file {
+.frame_file, .frame_library {
font-style: italic;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]