diff --git a/htdocs/core/modules/syslog/mod_syslog_sentry.php b/htdocs/core/modules/syslog/mod_syslog_sentry.php new file mode 100644 index 00000000000..3625405aeaa --- /dev/null +++ b/htdocs/core/modules/syslog/mod_syslog_sentry.php @@ -0,0 +1,187 @@ + + * Copyright (C) 2004-2009 Laurent Destailleur + * Copyright (C) 2015 Raphaƫl Doursenaud + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +require_once DOL_DOCUMENT_ROOT . '/includes/autoload.php'; +require_once DOL_DOCUMENT_ROOT . '/core/modules/syslog/logHandler.php'; + +/** + * Class to manage logging to Sentry + * + * @see https://docs.getsentry.com/on-premise/clients/php/ + */ +class mod_syslog_sentry extends LogHandler implements LogHandlerInterface +{ + /** + * @var string Log handler code + */ + public $code = 'sentry'; + + /** + * Return name of logger + * + * @return string Name of logger + */ + public function getName() + { + return 'Sentry'; + } + + /** + * Version of the module ('x.y.z' or 'dolibarr' or 'experimental' or 'development') + * + * @return string + */ + public function getVersion() + { + return 'dolibarr'; + } + + /** + * Content of the info tooltip. + * + * @return false|string + */ + public function getInfo() + { + global $langs; + return $langs->trans('SyslogSentryFromProject'); + } + + /** + * Is the module active ? + * + * @return int + */ + public function isActive() + { + return 1; + } + + /** + * Return array of configuration data + * + * @return array Return array of configuration data + */ + public function configure() + { + global $langs; + return array( + array( + 'constant' => 'SYSLOG_SENTRY_DSN', + 'name' => $langs->trans('SyslogSentryDSN'), + 'default' => '', + 'attr' => 'size="100" placeholder="https://:@app.getsentry.com/"' + ) + ); + } + + /** + * Return if configuration is valid + * + * @return array Array of errors. Empty array if ok. + */ + public function checkConfiguration() + { + global $conf; + + $errors = array(); + + $dsn = $conf->global->SYSLOG_SENTRY_DSN; + + try { + $client = new Raven_Client( + $dsn, + array('curl_method' => 'sync') + ); + } catch (InvalidArgumentException $ex) { + $errors[] = "ERROR: There was an error parsing your DSN:\n " . $ex->getMessage(); + } + + if (!$errors) { + // Send test event and check for errors + $client->captureMessage('TEST: Sentry syslog configuration check', null, Raven_Client::DEBUG); + $last_error = $client->getLastError(); + if ($last_error) { + $errors[] = $last_error; + } + } + + if (!$errors) { + // Install handlers + $error_handler = new Raven_ErrorHandler($client); + $error_handler->registerExceptionHandler(); + $error_handler->registerErrorHandler(); + $error_handler->registerShutdownFunction(); + } + + return $errors; + } + + /** + * Export the message + * + * @param array $content Array containing the info about the message + * @return void + */ + public function export($content) + { + global $conf; + $dsn = $conf->global->SYSLOG_SENTRY_DSN; + $client = new Raven_Client( + $dsn, + array('curl_method' => 'exec') + ); + + $client->user_context(array( + 'username' => ($content['user'] ? $content['user'] : ''), + 'ip_address' => $content['ip'] + )); + + $client->tags_context(array( + 'version' => DOL_VERSION + )); + + $client->registerSeverityMap(array( + LOG_EMERG => Raven_Client::FATAL, + LOG_ALERT => Raven_Client::FATAL, + LOG_CRIT => Raven_Client::ERROR, + LOG_ERR => Raven_Client::ERROR, + LOG_WARNING => Raven_Client::WARNING, + LOG_NOTICE => Raven_Client::WARNING, + LOG_INFO => Raven_Client::INFO, + LOG_DEBUG => Raven_Client::DEBUG, + )); + + if (substr($content['message'], 0, 3) === 'sql') { + global $db; + $query = substr($content['message'], 4, strlen($content['message'])); + $client->captureQuery( + $query, + $client->translateSeverity($content['level']), + $db->type + ); + } else { + $client->captureMessage( + $content['message'], + null, + $client->translateSeverity($content['level']) + ); + } + } +} diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 298c580c170..a52e9974564 100755 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1411,6 +1411,8 @@ SyslogFilename=File name and path YouCanUseDOL_DATA_ROOT=You can use DOL_DATA_ROOT/dolibarr.log for a log file in Dolibarr "documents" directory. You can set a different path to store this file. ErrorUnknownSyslogConstant=Constant %s is not a known Syslog constant OnlyWindowsLOG_USER=Windows only supports LOG_USER +SyslogSentryDSN=Sentry DSN +SyslogSentryFromProject=DSN from your Sentry project ##### Donations ##### DonationsSetup=Donation module setup DonationsReceiptModel=Template of donation receipt