#!/usr/bin/env perl # $Id: grabBZstats,v 1.2 2007/09/11 13:48:22 c4chris Exp $ # This script retrieves CSV formatted bug lists and extracts some stats on # open/close rates. # TODO stuff use strict; use Getopt::Long; use Date::Manip; use XMLRPC::Lite; my $rpc = new XMLRPC::Lite ( proxy => 'https://bugzilla.redhat.com/xmlrpc.cgi' ); # Not sure of the way to increase the timeout on reading... $rpc->transport->timeout(360); $main::BZusername = ""; $main::password = ""; my %opt; my @options = ( "help", "bu=s", "p=s" ); my @Ticket; my $startDate = ParseDate("1 August 2005"); if( ! GetOptions( \%opt, @options ) ) { &usage(); } # Override any default settings with arguments that the user has supplied $main::BZusername = $opt{"bu"} if defined $opt{"bu"}; $main::password = $opt{"p"} if defined $opt{"p"}; &usage() if defined $opt{'help'}; my $bA = &runQuery($rpc); foreach my $bug (@$bA) { # Try to guess package name my $name = $bug->{'short_desc'}; $bug->{'opendate'} = ParseDate($bug->{'opendate'}); $bug->{'changeddate'} = ParseDate($bug->{'changeddate'}); next if $name =~ /TESTING-BUGSPAM/; next if $name =~ /^.Tracker:/; push @Ticket, $bug; } my @SubmitSortedT = sort { Date_Cmp($a->{'opendate'}, $b->{'opendate'}) } @Ticket; my @ModifSortedT = sort { Date_Cmp($a->{'changeddate'}, $b->{'changeddate'}) } @Ticket; my $curDate = $startDate; my $openCount = 0; my @Open; foreach my $e (@SubmitSortedT) { if (Date_Cmp($e->{'opendate'}, $curDate) < 0) { $openCount += 1; next; } push @Open, $openCount; $openCount = 0; $curDate = DateCalc($curDate, "+ 1 week"); while (Date_Cmp($e->{'opendate'}, $curDate) >= 0) { push @Open, $openCount; $curDate = DateCalc($curDate, "+ 1 week"); } $openCount += 1; } push @Open, $openCount; $curDate = DateCalc($curDate, "+ 1 week"); while (Date_Cmp("today", $curDate) >= 0) { push @Open, 0; $curDate = DateCalc($curDate, "+ 1 week"); } $curDate = $startDate; my $closeCount = {}; my @Close; my @K = ("Accepted", "DUPLICATE", "Dropped"); foreach my $e (@ModifSortedT) { next if $e->{'bug_status'} ne "CLOSED"; my $key; $key = "Accepted" if $e->{'resolution'} =~ /^(CURRENTRELEASE|NEXTRELEASE|RAWHIDE|ERRATA)$/; $key = "DUPLICATE" if $e->{'resolution'} eq "DUPLICATE"; $key = "Dropped" if $e->{'resolution'} =~ /^(CANTFIX|DEFERRED|NOTABUG|WONTFIX|WORKSFORME|INSUFFICIENT_DATA|UPSTREAM)$/; unless (defined $key) { print STDERR $e->{'bug_id'}, ": ", $e->{'resolution'}, "\n"; die "Can't classify"; #$key = "Dropped"; } if (Date_Cmp($e->{'changeddate'}, $curDate) < 0) { $closeCount->{"all"} += 1; $closeCount->{$key} += 1; next; } push @Close, $closeCount; $closeCount = {}; $curDate = DateCalc($curDate, "+ 1 week"); while (Date_Cmp($e->{'changeddate'}, $curDate) >= 0) { push @Close, $closeCount; $closeCount = {}; $curDate = DateCalc($curDate, "+ 1 week"); } $closeCount->{"all"} += 1; $closeCount->{$key} += 1; } push @Close, $closeCount; $curDate = DateCalc($curDate, "+ 1 week"); while (Date_Cmp("today", $curDate) >= 0) { push @Close, {}; $curDate = DateCalc($curDate, "+ 1 week"); } my $cumOpen = 0; my $cumClose = 0; print "Week opened closed queue"; foreach my $k (@K) { print " $k"; } print "\n"; for my $i (0 .. $#Open) { my $c = $Close[$i]; $c->{"all"} = 0 unless defined $c->{"all"}; $cumOpen += $Open[$i]; $cumClose += $c->{"all"}; my $diff = $cumOpen - $cumClose; print "$i $Open[$i] $c->{'all'} $diff"; foreach my $k (@K) { $c->{$k} = 0 unless defined $c->{$k}; print " $c->{$k}"; } print "\n"; } exit 0; sub usage { print STDERR "Usage: $0 [options] where options are: -help this help note\n"; exit 1; } sub runQuery { my ($rpc) = @_; my $querydata = { 'column_list' => ['opendate', 'changeddate', 'bug_severity', 'alias', 'assigned_to', 'reporter', 'bug_status', 'resolution', 'component', 'blockedby', 'short_desc'], 'product' => ['Fedora'], 'component' => ['Package Review'], 'bug_status' => ["NEW", "VERIFIED", "ASSIGNED", "REOPENED", "NEEDINFO_ENG", "NEEDINFO", "INVESTIGATE", "MODIFIED", "ON_DEV", "UNCONFIRMED", "QA_READY", "ON_QA", "FAILS_QA", "NEEDINFO_REPORTER", "RELEASE_PENDING", "POST"] }; my $call; while (1) { print STDERR "Running runQuery(rpc) all open\n"; eval { $call = $rpc->call('bugzilla.runQuery', $querydata, $main::BZusername, $main::password); if ($call->faultstring) { print STDERR $call->faultstring . "\n"; exit 1; } }; if ($@) { warn $@; } else { last; } } my $result = $call->result; my $res_all = $result->{'bugs'}; $querydata->{'bug_status'} = ["CLOSED"]; while (1) { print STDERR "Running runQuery(rpc) closed\n"; eval { $call = $rpc->call('bugzilla.runQuery', $querydata, $main::BZusername, $main::password); if ($call->faultstring) { print STDERR $call->faultstring . "\n"; exit 1; } }; if ($@) { warn $@; } else { last; } } $result = $call->result; my $res2 = $result->{'bugs'}; push @$res_all, @$res2; return $res_all; }