Add ExceptionMailerCronjob
authorTim Düsterhus <duesterhus@woltlab.com>
Tue, 5 Mar 2019 13:24:36 +0000 (14:24 +0100)
committerTim Düsterhus <duesterhus@woltlab.com>
Tue, 5 Mar 2019 13:27:23 +0000 (14:27 +0100)
Closes #2654

com.woltlab.wcf/cronjob.xml
wcfsetup/install/files/lib/system/cronjob/ExceptionMailerCronjob.class.php [new file with mode: 0644]
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index c0dd47ff4cd536c1e83e1f9b8fc8ee87fa655ed4..affba31de8124f66a69931dd4d338297a8f3f3ab 100644 (file)
                        <startdow>*</startdow>
                        <canbedisabled>0</canbedisabled>
                </cronjob>
+               <cronjob name="com.woltlab.wcf.exceptionMailer">
+                       <classname>wcf\system\cronjob\ExceptionMailerCronjob</classname>
+                       <description>Sends out notifications about new entries in the error log.</description>
+                       <description language="de">Versendet Benachrichtigungen über neue Einträge im Fehlerprotokoll.</description>
+                       <startminute>0</startminute>
+                       <starthour>5</starthour>
+                       <startdom>*</startdom>
+                       <startmonth>*</startmonth>
+                       <startdow>*</startdow>
+               </cronjob>
        </import>
 </data>
diff --git a/wcfsetup/install/files/lib/system/cronjob/ExceptionMailerCronjob.class.php b/wcfsetup/install/files/lib/system/cronjob/ExceptionMailerCronjob.class.php
new file mode 100644 (file)
index 0000000..d5f502a
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+namespace wcf\system\cronjob;
+use wcf\data\cronjob\Cronjob;
+use wcf\system\email\mime\PlainTextMimePart;
+use wcf\system\email\Email;
+use wcf\system\email\Mailbox;
+use wcf\system\language\LanguageFactory;
+use wcf\system\registry\RegistryHandler;
+use wcf\util\ExceptionLogUtil;
+use wcf\util\StringUtil;
+
+/**
+ * Mails an Exception summary.
+ * 
+ * @author     Tim Duesterhus
+ * @copyright  2001-2019 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    WoltLabSuite\Core\System\Cronjob
+ * @since      5.2
+ */
+class ExceptionMailerCronjob extends AbstractCronjob {
+       /**
+        * @inheritDoc
+        */
+       public function execute(Cronjob $cronjob) {
+               parent::execute($cronjob);
+               
+               $timestamp = RegistryHandler::getInstance()->get('com.woltlab.wcf', 'exceptionMailerTimestamp');
+               $timestamp = max($timestamp, TIME_NOW - 86400 * 3);
+               for ($it = $timestamp; $it < TIME_NOW; $it += 86400) {
+                       $files[gmdate('Y-m-d', $it)] = [];
+               }
+               $files[gmdate('Y-m-d', TIME_NOW)] = [];
+               
+               $seen = [];
+               foreach ($files as $file => $value) {
+                       $path = WCF_DIR.'log/'.$file.'.txt';
+                       if (!file_exists($path)) {
+                               unset($files[$file]);
+                               continue;
+                       }
+                       // check log size (2MiB) to prevent resource exhaustion
+                       if (filesize($path) > 2 * (1 << 20)) {
+                               $files[$file] = [
+                                       'verdict' => 'huge'
+                               ];
+                               continue;
+                       }
+                       try {
+                               $exceptions = ExceptionLogUtil::splitLog(file_get_contents($path));
+                       }
+                       catch (\Exception $e) {
+                               $files[$file] = [
+                                       'verdict' => 'corrupt'
+                               ];
+                               continue;
+                       }
+                       
+                       $count = 0;
+                       $files[$file]['messages'] = [];
+                       foreach ($exceptions as $exception) {
+                               $exception = ExceptionLogUtil::parseException($exception);
+                               $message = $exception['message'];
+                               if ($exception['date'] < $timestamp) continue;
+                               
+                               $count++;
+                               if (!isset($seen[$message]) && count($files[$file]['messages']) < 3) {
+                                       $files[$file]['messages'][] = StringUtil::truncate(preg_replace('/\s+/', ' ', $message), 140);
+                                       $seen[$message] = true;
+                               }
+                       }
+                       if ($count == 0) {
+                               unset($files[$file]);
+                               continue;
+                       }
+                       
+                       $files[$file]['count'] = $count;
+               }
+               
+               if (empty($files)) return;
+               
+               $language = LanguageFactory::getInstance()->getDefaultLanguage();
+               
+               $email = new Email();
+               $email->addRecipient(new Mailbox(MAIL_ADMIN_ADDRESS, null, $language));
+               $email->setSubject($language->getDynamicVariable('wcf.acp.exceptionLog.email.subject', [
+                       'date' => $timestamp
+               ]));
+               $email->setBody(new PlainTextMimePart($language->getDynamicVariable('wcf.acp.exceptionLog.email.body', [
+                       'date' => $timestamp,
+                       'files' => $files
+               ])));
+               $email->send();
+               RegistryHandler::getInstance()->set('com.woltlab.wcf', 'exceptionMailerTimestamp', TIME_NOW);
+       }
+}
index 4d69a15693fdf312398f9865e560b47ba41f22a1..70f1efacb459525be02b31607475795616273b07 100644 (file)
                <item name="wcf.acp.exceptionLog.exception.date"><![CDATA[Datum]]></item>
                <item name="wcf.acp.exceptionLog.exception.userAgent"><![CDATA[Browser]]></item>
                <item name="wcf.acp.exceptionLog.exception.memory"><![CDATA[Arbeitsspeicher]]></item>
+               <item name="wcf.acp.exceptionLog.email.subject"><![CDATA[Fehlermeldungen seit {$date|plainTime}]]></item>
+               <item name="wcf.acp.exceptionLog.email.body"><![CDATA[Hallo Administrator,
+
+die folgenden Fehlermeldungen auf Ihrer Website {@PAGE_TITLE|language} wurden seit dem {$date|plainTime} protokolliert:
+
+{foreach from=$files key=file item=data}
+log/{$file}.txt {* this line ends with a space *}
+==================
+
+{if $data[verdict]|isset}
+{if $data[verdict] == 'corrupt'}
+Das Fehlerprotokoll ist defekt. Bitte prüfen Sie das Protokoll händisch: {'WCF_DIR'|constant}log/{$file}.txt
+{elseif $data[verdict] == 'huge'}
+Das Fehlerprotokoll ist sehr groß. Bitte prüfen Sie das Protokoll händisch: {'WCF_DIR'|constant}log/{$file}.txt
+{/if}
+{else}
+Das Fehlerprotokoll enthält {$data[count]} neue Einträge. Die ersten drei, in dieser E-Mail noch nicht genannten, Fehlermeldungen lauten:
+{foreach from=$data[messages] item=message}
+- {@$message} {* this line ends with a space *}
+{/foreach}
+{/if}
+{* this line is intentionally left empty *}
+{/foreach}]]></item>
        </category>
        <category name="wcf.acp.group">
                <item name="wcf.acp.group.add"><![CDATA[Benutzergruppe hinzufügen]]></item>
index 75993346a7f809841a790ab5bdfbe0a037de1bd9..e2a184b90874af734f8f5c4f1858b6f6b57da206 100644 (file)
                <item name="wcf.acp.exceptionLog.exception.date"><![CDATA[Time]]></item>
                <item name="wcf.acp.exceptionLog.exception.userAgent"><![CDATA[User Agent]]></item>
                <item name="wcf.acp.exceptionLog.exception.memory"><![CDATA[Memory]]></item>
+               <item name="wcf.acp.exceptionLog.email.subject"><![CDATA[Logged Errors since {$date|plainTime}]]></item>
+               <item name="wcf.acp.exceptionLog.email.body"><![CDATA[Dear Administrator,
+
+the following errors have been logged on your website {@PAGE_TITLE|language} since {$date|plainTime}:
+
+{foreach from=$files key=file item=data}
+log/{$file}.txt {* this line ends with a space *}
+==================
+
+{if $data[verdict]|isset}
+{if $data[verdict] == 'corrupt'}
+This protocol file is corrupted. Please check the protocol manually: {'WCF_DIR'|constant}log/{$file}.txt
+{elseif $data[verdict] == 'huge'}
+This protocol file is very large. Please check the protocol manually: {'WCF_DIR'|constant}log/{$file}.txt
+{/if}
+{else}
+This protocol file contains {$data[count]} new entries. The first three error messages that are not yet listed in this email are:
+{foreach from=$data[messages] item=message}
+- {@$message} {* this line ends with a space *}
+{/foreach}
+{/if}
+{* this line is intentionally left empty *}
+{/foreach}]]></item>
        </category>
        <category name="wcf.acp.group">
                <item name="wcf.acp.group.add"><![CDATA[Add User Group]]></item>