core: Add an option to suppress error reporting (#1179)

Error reporting currently takes place for each error. This can result
in many error messages if a server has connectivity issues (i.e. when
it re-connects to the internet every 24 hours).

This commit adds a new option to the configuration file to define the
number of error reports to suppress before returning an error message
to the user.

Error reports are cached and therefore automatically purged after 24
hours. A successful bridge request does **not** clear the error count
as sporadic issues can be the result of actual problems on the server.

The implementation currently makes no assumption on the type of error,
which means it also suppresses bridge errors in debug mode. The default
value is, however, set to 1 which means all errors are reported.

References #994
This commit is contained in:
LogMANOriginal 2019-10-31 18:49:45 +01:00 committed by GitHub
parent e8536ac1b2
commit 1022b5fdf9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 100 additions and 55 deletions

View File

@ -146,20 +146,61 @@ class DisplayAction extends ActionAbstract {
} catch(Error $e) {
error_log($e);
if(Configuration::getConfig('error', 'output') === 'feed') {
$item = new \FeedItem();
if(logBridgeError($bridge::NAME, $e->getCode()) >= Configuration::getConfig('error', 'report_limit')) {
if(Configuration::getConfig('error', 'output') === 'feed') {
$item = new \FeedItem();
// Create "new" error message every 24 hours
$this->userData['_error_time'] = urlencode((int)(time() / 86400));
// Create "new" error message every 24 hours
$this->userData['_error_time'] = urlencode((int)(time() / 86400));
// Error 0 is a special case (i.e. "trying to get property of non-object")
if($e->getCode() === 0) {
$item->setTitle(
'Bridge encountered an unexpected situation! ('
. $this->userData['_error_time']
. ')'
// Error 0 is a special case (i.e. "trying to get property of non-object")
if($e->getCode() === 0) {
$item->setTitle(
'Bridge encountered an unexpected situation! ('
. $this->userData['_error_time']
. ')'
);
} else {
$item->setTitle(
'Bridge returned error '
. $e->getCode()
. '! ('
. $this->userData['_error_time']
. ')'
);
}
$item->setURI(
(isset($_SERVER['REQUEST_URI']) ? parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) : '')
. '?'
. http_build_query($this->userData)
);
} else {
$item->setTimestamp(time());
$item->setContent(buildBridgeException($e, $bridge));
$items[] = $item;
} elseif(Configuration::getConfig('error', 'output') === 'http') {
header('Content-Type: text/html', true, $e->getCode());
die(buildTransformException($e, $bridge));
}
}
} catch(Exception $e) {
error_log($e);
if(logBridgeError($bridge::NAME, $e->getCode()) >= Configuration::getConfig('error', 'report_limit')) {
if(Configuration::getConfig('error', 'output') === 'feed') {
$item = new \FeedItem();
// Create "new" error message every 24 hours
$this->userData['_error_time'] = urlencode((int)(time() / 86400));
$item->setURI(
(isset($_SERVER['REQUEST_URI']) ? parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) : '')
. '?'
. http_build_query($this->userData)
);
$item->setTitle(
'Bridge returned error '
. $e->getCode()
@ -167,51 +208,14 @@ class DisplayAction extends ActionAbstract {
. $this->userData['_error_time']
. ')'
);
$item->setTimestamp(time());
$item->setContent(buildBridgeException($e, $bridge));
$items[] = $item;
} elseif(Configuration::getConfig('error', 'output') === 'http') {
header('Content-Type: text/html', true, $e->getCode());
die(buildTransformException($e, $bridge));
}
$item->setURI(
(isset($_SERVER['REQUEST_URI']) ? parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) : '')
. '?'
. http_build_query($this->userData)
);
$item->setTimestamp(time());
$item->setContent(buildBridgeException($e, $bridge));
$items[] = $item;
} elseif(Configuration::getConfig('error', 'output') === 'http') {
header('Content-Type: text/html', true, $e->getCode());
die(buildTransformException($e, $bridge));
}
} catch(Exception $e) {
error_log($e);
if(Configuration::getConfig('error', 'output') === 'feed') {
$item = new \FeedItem();
// Create "new" error message every 24 hours
$this->userData['_error_time'] = urlencode((int)(time() / 86400));
$item->setURI(
(isset($_SERVER['REQUEST_URI']) ? parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) : '')
. '?'
. http_build_query($this->userData)
);
$item->setTitle(
'Bridge returned error '
. $e->getCode()
. '! ('
. $this->userData['_error_time']
. ')'
);
$item->setTimestamp(time());
$item->setContent(buildBridgeException($e, $bridge));
$items[] = $item;
} elseif(Configuration::getConfig('error', 'output') === 'http') {
header('Content-Type: text/html', true, $e->getCode());
die(buildTransformException($e, $bridge));
}
}

View File

@ -70,6 +70,9 @@ password = ""
; "none" = No errors are reported
output = "feed"
; Defines how often an error must occur before it is reported to the user
report_limit = 1
; --- Cache specific configuration ---------------------------------------------
[SQLiteCache]

View File

@ -204,6 +204,10 @@ final class Configuration {
if(!is_string(self::getConfig('error', 'output')))
self::reportConfigurationError('error', 'output', 'Is not a valid String');
if(!is_numeric(self::getConfig('error', 'report_limit'))
|| self::getConfig('error', 'report_limit') < 1)
self::reportConfigurationError('admin', 'report_limit', 'Value is invalid');
}
/**

View File

@ -41,3 +41,37 @@ function returnClientError($message){
function returnServerError($message){
returnError($message, 500);
}
/**
* Stores bridge-specific errors in a cache file.
*
* @param string $bridgeName The name of the bridge that failed.
* @param int $code The error code
*
* @return int The total number the same error has appeared
*/
function logBridgeError($bridgeName, $code) {
$cacheFac = new CacheFactory();
$cacheFac->setWorkingDir(PATH_LIB_CACHES);
$cache = $cacheFac->create(Configuration::getConfig('cache', 'type'));
$cache->setScope('error_reporting');
$cache->setkey($bridgeName . '_' . $code);
$cache->purgeCache(86400); // 24 hours
if($report = $cache->loadData()) {
$report = json_decode($report, true);
$report['time'] = time();
$report['count']++;
} else {
$report = array(
'error' => $code,
'time' => time(),
'count' => 1,
);
}
$cache->saveData(json_encode($report));
return $report['count'];
}