5 use Digest::SHA1 qw(sha1_hex);
13 use vars qw($dbhost $dbname $dbuser $dbpass $dbport
14 $all_stat $fail_stat $change_stat $green_stat
17 require "$ENV{BFConfDir}/BuildFarmWeb.pl";
19 die "no dbname" unless $dbname;
20 die "no dbuser" unless $dbuser;
22 # don't use configged dbuser/dbpass
24 $dbuser=""; $dbpass="";
26 my $dsn="dbi:Pg:dbname=$dbname";
27 $dsn .= ";host=$dbhost" if $dbhost;
28 $dsn .= ";port=$dbport" if $dbport;
30 my $db = DBI->connect($dsn,$dbuser,$dbpass);
32 die $DBI::errstr unless $db;
34 my $clear_old = $db->do(q[
38 (SELECT name FROM buildsystems WHERE no_alerts)
42 my $sth = $db->prepare(q[
44 SELECT DISTINCT ON (sysname, branch)
46 extract(epoch from snapshot at time zone 'GMT')::int as snapshot,
48 FROM build_status s join buildsystems b on (s.sysname = b.name)
49 WHERE NOT b.no_alerts and
50 snapshot > current_timestamp - interval '30 days'
51 ORDER BY sysname, branch, snapshot desc
59 while (my $row = $sth->fetchrow_hashref)
61 push(@last_heard, $row);
68 SELECT sysname, branch,
69 extract(epoch from first_alert) as first_alert,
70 extract(epoch from last_notification) as last_notification
75 my $alerts = $db->selectall_hashref($sql,['sysname','branch']);
80 my $clear_sth = $db->prepare(q[
87 my $update_sth = $db->prepare(q[
90 SET last_notification = timestamp '1970-01-01' + ( interval '1 second' * $1)
95 my $insert_sth = $db->prepare(q[
97 INSERT INTO alerts ( sysname, branch, first_alert, last_notification )
99 timestamp '1970-01-01' + ( interval '1 second' * $3),
100 timestamp '1970-01-01' + ( interval '1 second' * $4))
105 my $lts = scalar(localtime);
106 print "starting alert run: $lts\n";
108 foreach my $sysbranch (@last_heard)
110 # eval the config in a Safe container to protect ourselves
111 my $container = new Safe;
112 my $sconf = $sysbranch->{config};
113 unless ($sconf =~ s/.*(\$Script_Config)/$1/ms )
115 $sconf = '$Script_Config={};';
117 my $client_conf = $container->reval("$sconf;");
119 my %client_alert_settings = %{ $client_conf->{alerts} || {} };
120 my $setting = $client_alert_settings{$sysbranch->{branch}};
121 unless ($setting && $setting->{alert_after} && $setting->{alert_every})
123 # if no valid setting, clear any alert and keep going
124 if ($alerts->{$sysbranch->{sysname}}->{$sysbranch->{branch}})
126 $clear_sth->execute($sysbranch->{sysname},$sysbranch->{branch});
127 push(@need_cleared,[$sysbranch]);
131 # ok, we have valid settings. should the alert be on?
132 my $hours_since_heard = ($now - $sysbranch->{snapshot}) / 3600;
135 "have settings for $sysbranch->{sysname}:$sysbranch->{branch} ",
136 "hours since heard = $hours_since_heard, ",
137 "setting = $setting->{alert_after} / $setting->{alert_every} \n";
139 if ($hours_since_heard > $setting->{alert_after})
142 $alerts->{$sysbranch->{sysname}}->{$sysbranch->{branch}};
144 ($now - (3600 * $setting->{alert_every})) >
145 $known_alert->{last_notification})
147 # check if it's too old - 15 days and twice initial seems plenty
148 if ($hours_since_heard > 360 &&
149 $hours_since_heard > 2 * $setting->{alert_after} )
151 print "alert is too old ... giving up\n";
155 # old alert, but time to alert again
156 print "alert is on, but time to alert again\n";
157 $update_sth->execute($now,
158 $sysbranch->{sysname},
159 $sysbranch->{branch},
161 push(@need_alerts,[$sysbranch,$setting]);
162 print "alert updated\n";
164 elsif ( ! $known_alert )
167 print "new alert needed\n";
168 $insert_sth->execute($sysbranch->{sysname},
169 $sysbranch->{branch},
171 print "new record inserted\n";
172 push(@need_alerts,[$sysbranch,$setting]);
175 # nope, so clear the alert if it exists
176 elsif ($alerts->{$sysbranch->{sysname}}->{$sysbranch->{branch}})
178 print "clear exisiting alerts";
179 $clear_sth->execute($sysbranch->{sysname},$sysbranch->{branch});
180 push(@need_cleared,[$sysbranch,$setting]);
185 print "start emails\n";
187 my $addr_sth = $db->prepare(q[
195 my $me = `id -un`; chomp $me;
197 my $host = `hostname`; chomp $host;
201 foreach my $clearme (@need_cleared)
203 my ($sysbranch, $setting) = @$clearme;
204 my ($animal, $branch) = ($sysbranch->{sysname},$sysbranch->{branch});
208 my $hours = ($now - $sysbranch->{snapshot}) / 3600;
209 $text = "$sysbranch->{sysname} has now reported " .
210 "on $sysbranch->{branch} $hours hours ago.";
214 $text = "$sysbranch->{sysname} has lost alarm settings on branch: " .
215 "$sysbranch->{branch}. Resetting alarm to off.";
217 my $msg = new Mail::Send;
219 $msg->set('From',"PG Build Farm <$me\@$host>");
221 $addr_sth->execute($animal);
223 my $mailto = $addr_sth->fetchrow_array;
225 print "sending clear to $mailto\n";
230 $msg->subject("PGBuildfarm member $animal Branch $branch Alert cleared");
232 print $fh "\n\n$text\n";
235 print "alert cleared $animal $branch\n";
238 foreach my $clearme (@need_alerts)
240 my ($sysbranch, $setting) = @$clearme;
241 my ($animal, $branch) = ($sysbranch->{sysname},$sysbranch->{branch});
242 my $hours = ($now - $sysbranch->{snapshot}) / 3600;
243 my $text = "$sysbranch->{sysname} has not reported " .
244 "on $sysbranch->{branch} for $hours hours.";
245 my $msg = new Mail::Send;
247 $msg->set('From',"PG Build Farm <$me\@$host>");
249 $addr_sth->execute($animal);
251 my ($mailto) = $addr_sth->fetchrow_array;
255 print "sending alert to $mailto\n";
259 $msg->subject("PGBuildfarm member $animal Branch $branch " .
260 "Alert notification");
262 print $fh "\n\n$text\n";
265 print "alert sent $animal $branch\n";
269 print "=================================\n";