Hintergrundjob für E-Mail-Bericht über fehlgeschlagene Jobs
authorMoritz Bunkus <m.bunkus@linet-services.de>
Thu, 19 Feb 2015 15:47:30 +0000 (16:47 +0100)
committerSven Schöling <s.schoeling@linet-services.de>
Thu, 5 Mar 2015 12:42:59 +0000 (13:42 +0100)
SL/BackgroundJob/ALL.pm
SL/BackgroundJob/FailedBackgroundJobsReport.pm [new file with mode: 0644]
scripts/locales.pl
templates/webpages/failed_background_jobs_report/email.txt [new file with mode: 0644]

index 84c55ee..ba9ce83 100644 (file)
@@ -6,6 +6,7 @@ use SL::BackgroundJob::Base;
 use SL::BackgroundJob::BackgroundJobCleanup;
 use SL::BackgroundJob::CleanBackgroundJobHistory;
 use SL::BackgroundJob::CreatePeriodicInvoices;
+use SL::BackgroundJob::FailedBackgroundJobsReport;
 
 1;
 
diff --git a/SL/BackgroundJob/FailedBackgroundJobsReport.pm b/SL/BackgroundJob/FailedBackgroundJobsReport.pm
new file mode 100644 (file)
index 0000000..e0bea8b
--- /dev/null
@@ -0,0 +1,155 @@
+package SL::BackgroundJob::FailedBackgroundJobsReport;
+
+use strict;
+use utf8;
+
+use parent qw(SL::BackgroundJob::Base);
+
+use SL::DB::BackgroundJobHistory;
+use SL::Locale::String;
+use SL::Mailer;
+
+use Rose::Object::MakeMethods::Generic (
+  scalar => [ qw(data start_time entries) ],
+);
+
+
+sub create_job {
+  # Don't create this job by default
+  1;
+}
+
+sub check_config {
+  my ($self) = @_;
+
+  die "No »recipients« specified" unless @{ $self->data->{recipients} || [] };
+  die "No »from« specified"       unless $self->data->{from};
+  die "No »subject« specified"    unless $self->data->{subject};
+
+  return $self;
+}
+
+sub send_email {
+  my ($self) = @_;
+
+  return 1 unless @{ $self->entries };
+
+  my $template  = Template->new({
+    INTERPOLATE => 0,
+    EVAL_PERL   => 0,
+    ABSOLUTE    => 1,
+    CACHE_SIZE  => 0,
+  }) || die("Could not create Template instance");
+
+  my $file_name = $self->data->{template} || 'templates/webpages/failed_background_jobs_report/email.txt';
+  my $body;
+  $template->process($file_name, { SELF => $self }, \$body);
+  $body = Encode::decode('utf-8', $body);
+
+  Mailer->new(
+    from         => $self->data->{from},
+    to           => join(', ', @{ $self->data->{recipients} }),
+    subject      => $self->data->{subject},
+    content_type => 'text/plain',
+    charset      => 'utf-8',
+    message      => $body,
+  )->send;
+
+  return $self;
+}
+
+sub load_failed_entries {
+  my ($self) = @_;
+
+  $self->start_time(DateTime->now_local->subtract(days => 1));
+  $self->entries([ @{ SL::DB::Manager::BackgroundJobHistory->get_all(
+    sort_by  => 'run_at ASC',
+    where    => [
+      status => SL::DB::BackgroundJobHistory::FAILURE(),
+      run_at => { ge => $self->start_time },
+    ],
+  )}]);
+
+  return $self;
+}
+
+sub run {
+  my ($self, $db_obj) = @_;
+
+  $self->data($db_obj->data_as_hash);
+
+  $self
+    ->check_config
+    ->load_failed_entries
+    ->send_email;
+
+  return 1;
+}
+
+1;
+__END__
+
+=pod
+
+=encoding utf8
+
+=head1 NAME
+
+SL::BackgroundJob::FailedBackgroundJobsReport - A background job
+checking for failed jobs and reporting them via email
+
+=head1 OVERVIEW
+
+This background's job is to watch over other background jobs. It will
+determine when it has run last and look for job history entries that
+have failed between the last run and the current time.
+
+If that search yields results then an email will be sent listing the
+jobs that failed and the error messages they produced. The template
+used for the email's body defaults to the file
+C<templates/webpages/failed_background_jobs_report/email.txt> but can
+be overridden in the configuration.
+
+This background job is not active by default. You have to add and
+configure it manually.
+
+=head1 CONFIGURATION
+
+This background job requires configuration data stored in its data
+member. This is supposed to be a YAML-encoded hash of the following
+options:
+
+=over 4
+
+=item * C<from> – required; the sender's email address used in the
+mail headers
+
+=item * C<recipients> – required; an array of email addresses for the
+recipients
+
+=item * C<subject> – required; the email's subject
+
+=item * C<template> – optional; a file name pointing to the template
+file used for the email's body. This defaults to
+C<templates/webpages/failed_background_jobs_report/email.txt>.
+
+=back
+
+Here's an example of how this data looks like:
+
+  ---
+  from: kivitendo@meine.firma
+  recipients:
+    - johanna.admin@meine.firma
+  subject: Fehlgeschlagene kivitendo-Jobs der letzten 24h
+  template: templates/mycompany/faileed_background_jobs_email.txt
+
+=head1 BUGS
+
+Nothing here yet.
+
+=head1 AUTHOR
+
+Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
+
+=cut
index 51db82f..eb1d81b 100755 (executable)
@@ -49,7 +49,8 @@ our $missing     = {};
 our @lost        = ();
 
 my %ignore_unused_templates = (
-  map { $_ => 1 } qw(ct/testpage.html generic/autocomplete.html oe/periodic_invoices_email.txt part/testpage.html t/render.html t/render.js task_server/failure_notification_email.txt)
+  map { $_ => 1 } qw(ct/testpage.html generic/autocomplete.html oe/periodic_invoices_email.txt part/testpage.html t/render.html t/render.js task_server/failure_notification_email.txt
+                     failed_background_jobs_report/email.txt)
 );
 
 my (%referenced_html_files, %locale, %htmllocale, %alllocales, %cached, %submit, %jslocale);
diff --git a/templates/webpages/failed_background_jobs_report/email.txt b/templates/webpages/failed_background_jobs_report/email.txt
new file mode 100644 (file)
index 0000000..506a9b7
--- /dev/null
@@ -0,0 +1,12 @@
+Hallo,
+
+die folgenden Hintergrundjobs sind seit [% SELF.start_time.to_kivitendo %] [% SELF.start_time.to_kivitendo_time %] ausgeführt worden und schlugen fehl:
+
+[%- FOREACH entry = SELF.entries %]
+Paketname:     [% entry.package_name %]
+Ausgeführt um: [% entry.run_at.to_kivitendo %] [% entry.run_at.to_kivitendo_time %]
+Fehler:        [% entry.error_col %]
+[% UNLESS loop.last %]============================================================[% END %]
+[%- END %]
+Gruß,
+kivitendo