Skip to content

Commit

Permalink
core: Add an option to suppress error reporting (#1179)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
logmanoriginal authored Oct 31, 2019
1 parent e8536ac commit 1022b5f
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 55 deletions.
114 changes: 59 additions & 55 deletions actions/DisplayAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,72 +146,76 @@ public function execute() {
} 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));

// 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)
);

// Create "new" error message every 24 hours
$this->userData['_error_time'] = urlencode((int)(time() / 86400));
$item->setTimestamp(time());
$item->setContent(buildBridgeException($e, $bridge));

// 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']
. ')'
$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)
);
} 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)
);

$item->setTimestamp(time());
$item->setContent(buildBridgeException($e, $bridge));
$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));
$items[] = $item;
} elseif(Configuration::getConfig('error', 'output') === 'http') {
header('Content-Type: text/html', true, $e->getCode());
die(buildTransformException($e, $bridge));
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions config.default.ini.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@
; "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]
Expand Down
4 changes: 4 additions & 0 deletions lib/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ public static function loadConfiguration() {
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');

}

/**
Expand Down
34 changes: 34 additions & 0 deletions lib/error.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'];
}

0 comments on commit 1022b5f

Please sign in to comment.