source: branches/tree/SOURCE_TOOLS/short_error_summary.pl

Last change on this file was 19762, checked in by westram, 3 weeks ago
  • tweak error excerpt:
    • suppress several unwanted lines.
    • adds target REEXTRACT for testing.
    • warn about empty excerpt
  • Property svn:executable set to *
File size: 4.3 KB
Line 
1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6my $DEBUG = 0;
7# Hint: use 'make REEXTRACT' to re-extract from BUILD_LOG generated by previous 'make ALL' or similar
8
9my $DISPLAYED_LINES = 40; # how much to display as default
10{
11  my $DARWIN = $ENV{DARWIN}; die "expected environment variable DARWIN to be defined" if not defined $DARWIN;
12  if ($DARWIN) {
13    # check for homebrew build:
14    my $HOMEBREW_OS_VERSION = $ENV{HOMEBREW_OS_VERSION};
15    if (defined($HOMEBREW_OS_VERSION) and ($HOMEBREW_OS_VERSION ne '')) {
16      # assume this is a homebrew build!
17      my $HOMEBREW_FAIL_LOG_LINES=$ENV{HOMEBREW_FAIL_LOG_LINES};
18      if (defined($HOMEBREW_FAIL_LOG_LINES) and (int($HOMEBREW_FAIL_LOG_LINES)>0)) {
19        $DISPLAYED_LINES = $HOMEBREW_FAIL_LOG_LINES;
20      }
21      else {
22        $DISPLAYED_LINES = 15; # =default
23      }
24    }
25  }
26}
27$DISPLAYED_LINES -= (1+2); # reserve space for header line + two extra lines shown after excerpt
28
29sub min($$) { my ($a, $b) = @_; return $a<$b ? $a : $b; }
30
31sub disarm($) {
32  my ($line) = @_;
33  $line =~ s/:/;/go; # avoid output gets interpreted as error message
34  return $line;
35}
36
37my $P_STAR = 2;
38my $P_FAILED = 4;
39my $MAXPRIO  = 4;
40
41my @count_prio = ();
42for (my $i=0; $i<=$MAXPRIO; ++$i) { $count_prio[$i] = 0; }
43
44my @listed = (); # contains refs to arrays containing [priority, line]
45
46sub list_error($$) {
47  my ($priority, $line) = @_;
48
49  die if $priority>$MAXPRIO;
50  return if not $priority;
51  return if $priority==$P_STAR and $line =~ /Waiting for unfinished jobs/o;
52  return if $line =~ /warning:/io;
53
54  chomp($line);
55
56  if ($priority==$P_STAR and scalar(@listed)) {
57    my $prev_r = $listed[$#listed];
58    my ($prevPrio, $prevLine) = @$prev_r;
59    if ($prevPrio==$P_FAILED and $prevLine =~ /recipe.*failed/io) {
60      # seen a line with '***' after 'recipe...failed' -> concat
61      pop @listed;
62      $line .= ' + '.$prevLine;
63      --$count_prio[$prevPrio];
64    }
65  }
66
67  push @listed, [ $priority, $line ];
68  ++$count_prio[$priority];
69}
70
71my %seen = (); # key=error-line; value=number of occurrences
72
73sub remove_duplicate_lines() {
74  @listed =
75    grep defined,
76    map {
77    my ($priority, $line) = @$_;
78    if (not exists $seen{$line}) {
79      $seen{$line} = 1;
80      $_;
81    }
82    else {
83      $seen{$line}++;
84      --$count_prio[$priority];
85      undef;
86    }
87  } @listed;
88}
89
90sub print_listed() {
91  my @allowed_with_prio = ();
92  my @printed_with_prio = ();
93
94  my $left = $DISPLAYED_LINES;
95
96  for (my $i=1; $i<=$MAXPRIO; ++$i) {
97    my $use = min($count_prio[$i], $left);
98    $left -= $use;
99    $allowed_with_prio[$i] = $use;
100    $printed_with_prio[$i] = 0;
101
102    if ($DEBUG) {
103      if ($count_prio[$i]>0) {
104        print STDERR "priority $i: ".$count_prio[$i]." (allowed=".$allowed_with_prio[$i].")\n";
105      }
106    }
107  }
108
109  foreach my $entry_r (@listed) {
110    my ($priority, $line) = @$entry_r;
111    if ($printed_with_prio[$priority] < $allowed_with_prio[$priority]) {
112      my $dupcount = $seen{$line};
113      my $disarmedLine = disarm($line);
114      if ($dupcount>1) {
115        $disarmedLine .= " [occurred ".($dupcount==2 ? "twice]" : "$dupcount times]");
116      }
117      if ($DEBUG) {
118        print STDERR $priority.' | '.$disarmedLine."\n";
119      }
120      else {
121        print STDERR $disarmedLine."\n";
122      }
123      ++$printed_with_prio[$priority];
124    }
125  }
126
127  my $printedAny = grep { defined $_ && $_ > 0 } @printed_with_prio;
128  if (not $printedAny) { print STDERR "no obvious errors found :-(\n"; }
129}
130
131sub short_error_summary() {
132  my $log = shift @ARGV;
133  die "Usage: short_error_summary.pl LOGNAME" if not defined $log;
134
135  open(LOG, '<'.$log) || die "failed to open '$log' (Reason: $!)";
136  print STDERR "---------------------------------------- [excerpt of obvious errors below; full log in $log]\n";
137  while (defined($_ = <LOG>)) {
138    my $priority = 0;
139    if    (/error:/io) {
140      $priority = 1;
141    }
142    elsif (/\*\*\*/o) {
143      $priority = $P_STAR;
144    }
145    # match 'error',  but not '-Werror-implicit-function-declaration' or 'arb_error':
146    elsif (/(?<!-W)(?<!\barb_)error/io) {
147      $priority = 3;
148    }
149    # match 'failed', but not 'failed_' or 'Failed : 0 =  0.0%' (=test success):
150    elsif (/failed(?!_)(?![\s:0=\.%]+$)/io) {
151      $priority = $P_FAILED;
152    }
153
154    list_error($priority, $_);
155  }
156  close(LOG);
157  remove_duplicate_lines();
158  print_listed();
159}
160
161short_error_summary();
Note: See TracBrowser for help on using the repository browser.