status = false;
try {
register_shutdown_function(array($this, '__destruct'));
$this->errStack = [];
$this->haveErrors = false;
$this->haveWarnings = false;
$this->haveFatals = false;
$this->publishMessage = $_pm;
$this->eventGUID = (!is_null($_eg) and validateGUID($_eg)) ? $_eg : null;
$this->validTemplates = [TEMPLATE_CLASS_LOGS, TEMPLATE_CLASS_METRICS];
// toss a fatal if the config hasn't been instantiated...
if (!isset(gasConfig::$settings) or empty(gasConfig::$settings)) {
$this->throwFatal(__FILE__ . '(' . __LINE__ . '): ' . ERROR_CONFIG_404);
} elseif (empty(gasConfig::$settings[CONFIG_DATABASE][CONFIG_DATABASE_MONGODB])) {
$this->throwFatal(__FILE__ . '(' . __LINE__ . '): ' . ERROR_CONFIG_RESOURCE_404 . RESOURCE_DDB);
}
// $this->config = gasConfig::$settings[CONFIG_DATABASE][CONFIG_DATABASE_DDB];
// $this->connection = $this->getNoSQLResource(); // ddb connection
$this->config = gasConfig::$settings[CONFIG_DATABASE][CONFIG_DATABASE_MONGODB];
$this->connection = gasResourceManager::fetchResource(RESOURCE_MONGO_MASTER, ENV_ADMIN);
$this->available = (!is_null($this->connection)) ? true : false;
$this->env = gasConfig::$settings[CONFIG_ID][CONFIG_ID_ENV];
$this->dbName = $this->env . UDASH . $this->config[CONFIG_DATABASE_MONGODB_ADMIN][CONFIG_DATABASE_MONGODB_DB_NAME];
// $this->abc = null;
$this->status = true;
} catch (TypeError | Throwable $e) {
$hdr = basename(__METHOD__) . AT . __LINE__ . COLON;
echo getDateTime() . CON_ERROR . $this->res . $hdr . $e->getMessage();
}
}
/**
* setService() -- public method
*
* When any class that extends core creates an embedded logger class, which they all should, then the instantiation
* class should call this function s.t. the logger class inherits (sloppily) the service defined for the current
* class. This will validated later in the function: isServiceLocal() when we're instantiating a class to ensure
* that a class can only be instantiated in it's service when we're dealing with appServer and tercero classes.
*
* There is a single input parameter to the function that is the defined name of the current service. We're not
* validating this string value b/c that's happened already within the "parent" class.
*
* @author mike@givingassistant.org
* @version 1.0
*
* @param string $_service
* @return bool
*
* HISTORY:
* ========
* 11-04-20 mks DB-171: original coding
*
*/
public function setService(string $_service):bool
{
if (isset(gasConfig::$settings[$_service]))
if (gasConfig::$settings[$_service][CONFIG_IS_LOCAL])
$this->service = $_service;
else {
$hdr = sprintf(INFO_LOC, basename(__METHOD__), __LINE__);
$msg = sprintf(ERROR_SERVICE_NOT_LOCAL, $_service);
consoleLog('SSER: ', CON_ERROR, $hdr . $msg);
return false;
}
else {
$hdr = sprintf(INFO_LOC, basename(__METHOD__), __FILE__);
$msg = ERROR_CONFIG_RESOURCE_404 . STRING_SERVICE;
consoleLog('SSER: ', CON_ERROR, $hdr . $msg);
return false;
}
return true;
}
/**
* throwFatal() -- private method
*
* if the logger cannot be properly instantiated, (thereby being unable to log errors in the database), the the
* last remaining option is to throw a direMessage (tm) to the console.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
* @param string $_msg -- the text dumped to the php-errors log
* @throws Exception
*
* HISTORY:
* ========
* 06-07-17 mks original coding
* 12-07-17 mks CORE-591: removed errStack dump b/c cached and can be recovered
* 01-22-18 mks _INF-139: updated code to php 7.2
* 03-02-18 mks CORE-680: deprecated trace logging
*
*/
private function throwFatal(string $_msg): void
{
$msg = PHP_EOL . '----------------------------------------------------------------------------------------------------' . PHP_EOL;
$msg .= ' FATAL ERRORS OCCURRED IN THE ERROR CLASS. EVALUATE, FIX, AND RE-RUN.' . PHP_EOL;
$msg .= PHP_EOL . $_msg . PHP_EOL;
$msg .= '----------------------------------------------------------------------------------------------------' . PHP_EOL;
throw new Exception($msg);
}
public function debug(string $_message): void
{
try {
self::set(ERROR_DEBUG, $_message);
} catch (Throwable $t) {
$msg = sprintf(INFO_LOC, basename(__FILE__), __LINE__) . ERROR_THROWABLE_EXCEPTION . COLON . $t->getMessage();
consoleLog($this->res, CON_ERROR, $msg);
}
}
public function info(string $_message): void
{
try {
self::set(ERROR_INFO, $_message);
} catch (Throwable $t) {
$msg = sprintf(INFO_LOC, basename(__FILE__), __LINE__) . ERROR_THROWABLE_EXCEPTION . COLON . $t->getMessage();
consoleLog($this->res, CON_ERROR, $msg);
}
}
public function data(string $_message): void
{
try {
self::set(ERROR_DATA, $_message);
} catch (Throwable $t) {
$msg = sprintf(INFO_LOC, basename(__FILE__), __LINE__) . ERROR_THROWABLE_EXCEPTION . COLON . $t->getMessage();
consoleLog($this->res, CON_ERROR, $msg);
}
}
public function error(string $_message): void
{
try {
self::set(ERROR_ERROR, $_message);
} catch (Throwable $t) {
$msg = sprintf(INFO_LOC, basename(__FILE__), __LINE__) . ERROR_THROWABLE_EXCEPTION . COLON . $t->getMessage();
consoleLog($this->res, CON_ERROR, $msg);
}
}
public function warn(string $_message): void
{
try {
self::set(ERROR_WARN, $_message);
} catch (Throwable $t) {
$msg = sprintf(INFO_LOC, basename(__FILE__), __LINE__) . ERROR_THROWABLE_EXCEPTION . COLON . $t->getMessage();
consoleLog($this->res, CON_ERROR, $msg);
}
}
public function fatal(string $_message): void
{
try {
self::set(ERROR_FATAL, $_message);
} catch (Throwable $t) {
$msg = sprintf(INFO_LOC, basename(__FILE__), __LINE__) . ERROR_THROWABLE_EXCEPTION . COLON . $t->getMessage();
consoleLog($this->res, CON_ERROR, $msg);
}
}
public function metrics(string $_message, float $_time, &$_es = null): void
{
try {
self::set(ERROR_METRICS, $_message, true, $_time, $_es);
} catch (Throwable $t) {
$msg = sprintf(INFO_LOC, basename(__FILE__), __LINE__) . ERROR_THROWABLE_EXCEPTION . COLON . $t->getMessage();
consoleLog($this->res, CON_ERROR, $msg);
}
}
/**
* set() -- public method
*
* this method is where most of the work gets done for the class.
*
* this method accepts a log level and a log message. if AMQP and nosql services are not available (either),
* then the message will be output to the console.
*
* otherwise, we're going to parse the log level against the configuration settings to ensure that we're
* publishing messages according to the settings and the current environment. (iow, don't publish debug level
* messages while in a production environment)
*
* RULES:
* ------
* DEBUG errors are only logged if debug mode is on
*
* we use debug_backtrace to generate the originating message data points and assemble the message data
* (and the meta data for the broker request) into a single array which is then processed and published
* to the delayed-write queue (itself a fire-and-forget queue).
*
* this design differs from previous iterations in that we're no longer trying to preserve an ongoing error
* stack - instead we're just considering the incoming message to be the only message currently in existence.
*
* The input parameters to the method are:
*
* $_level - which is the message level and a defined constant
* $_message - the text of the actual message
* $_metrics - (optional, default = false) if true, use the metrics template instead of the logs template
* $_t - (optional, default = 0), for metrics, the total query time
* $_es - (optional, default = 0), call-by-reference param to store/return the metrics error stack
*
* There are no return values, either implicitly or explicitly.
*
* @author mike@givingassistant.org
* @version 1.0
*
* @param string $_level error level
* @param string $_message error message string
* @param bool $_metrics defines the event as a metric (instead of an error) event
* @param float $_t time, in ms
* @param array $_es error stack: call by reference array stack/container
* @throws Exception
*
*
* HISTORY:
* ========
* 06-07-17 mks original coding
* 07-12-17 mks added log-level values to collection/processing
* 12-08-17 mks CORE-591: new throw-fatal processing
* 03-02-18 mks CORE-680: deprecated trace logging
* 06-08-18 mks CORE-1034: deprecating XML prodBox tag
* 07-30-18 mks CORE-774: PHP7.2 exception handling update
* 09-24-19 mks DB-136: fixed error in levelValues element assignment to correct constant
* 11-04-20 mks DB-171: added service (origin) definition to logging output
*
*/
private function set(string $_level, string $_message, bool $_metrics = false, float $_t = 0, array &$_es = null): void
{
$this->errStack = [];
$levelValues = [
ERROR_EVENT => ERROR_EVENT_VAL,
ERROR_METRICS => ERROR_METRICS_VAL,
ERROR_DEBUG => ERROR_DEBUG_VAL,
ERROR_DATA => ERROR_DATA_VAL,
ERROR_INFO => ERROR_INFO_VAL,
ERROR_ERROR => ERROR_ERROR_VAL,
ERROR_WARN => ERROR_WARN_VAL,
ERROR_FATAL => ERROR_FATAL_VAL
];
if (!array_key_exists($_level, $levelValues)) {
$this->throwFatal(__FILE__ . COLON . __LINE__ . COLON . sprintf(ERROR_UNKNOWN_KEY, $_level, LOG_VALUE));
$_level = ERROR_ERROR;
}
// the system is up - so create the error message request for publication to the DW broker
$_message = empty($_message) ? ERROR_DATA_INPUT_EMPTY : trim($_message);
switch ($_level) {
case ERROR_DEBUG :
$saveError = gasConfig::$settings[CONFIG_DEBUG] and !(gasConfig::$settings[CONFIG_ID][CONFIG_ID_ENV] == ENV_PRODUCTION);
break;
case ERROR_DATA :
case ERROR_INFO :
case ERROR_METRICS :
$saveError = true;
break;
case ERROR_ERROR :
$this->haveErrors = true;
$saveError = true;
break;
case ERROR_WARN :
$this->haveWarnings = true;
$saveError = true;
break;
case ERROR_FATAL :
$this->haveFatals = true;
$saveError = true;
break;
default :
$saveError = true;
$_level = ERROR_INFO;
break;
}
if (!$saveError) return;
try {
if ($_level == ERROR_METRICS) {
$this->isMetric = true;
$this->setCollection(TEMPLATE_CLASS_METRICS);
} else {
$this->setCollection();
}
} catch (Throwable $t) {
consoleLog($this->res, CON_ERROR, ERROR_THROWABLE_EXCEPTION . COLON . $t->getMessage());
}
if (is_array($_message)) {
$_message = implode('
', $_message);
}
$backTrace = debug_backtrace();
for ($index = 0; $index < 3; $index++) {
if (isset($backTrace[$index][STRING_FUNCTION]) and $backTrace[$index][STRING_FUNCTION] != STRING_SET)
break;
}
// if (isset($backTrace[2][ERROR_FILE])) {
// $index = 2;
// } elseif (isset($backTrace[1][ERROR_FILE])) {
// $index = 1;
// } else {
// $index = 0;
// }
$errStack = null;
if (empty($this->errStack)) $this->errStack = array();
if ($_level == ERROR_METRICS) @$errStack[(LOG_EVENT . $this->ext)] = EVENT_METRICS;
@$errStack[(LOG_FILE . $this->ext)] = $this->service . ARROW . $backTrace[$index][ERROR_FILE];
@$errStack[(LOG_LINE . $this->ext)] = $backTrace[$index][ERROR_LINE];
@$errStack[(LOG_METHOD . $this->ext)] = $backTrace[$index+1][STRING_FUNCTION];
@$errStack[(LOG_CLASS . $this->ext)] = $backTrace[$index+1][ERROR_CLASS];
@$errStack[(LOG_LEVEL . $this->ext)] = $_level;
@$errStack[(LOG_VALUE . $this->ext)] = $levelValues[$_level];
@$errStack[(LOG_MESSAGE . $this->ext)] = utf8_encode($_message);
if (isset($this->eventGUID))
@$errStack[(DB_EVENT_GUID . $this->ext)] = $this->eventGUID;
if ($_metrics) {
@$errStack[(LOG_TIMER . $this->ext)] = $_t;
$_es = $backTrace;
}
$errStack[(LOG_CREATED . $this->ext)] = time();
array_push($this->errStack, $errStack);
try {
$this->writeLogMessage();
if ($this->mirror) {
consoleLog($this->res, CON_ERROR, $_message);
}
} catch (Throwable $t) {
consoleLog($this->res, CON_ERROR, ERROR_THROWABLE_EXCEPTION . COLON . $t->getMessage());
}
}
/**
* writeLogMessage() -- public static method
*
* this is the record-create method for saving a log event.
*
* There are three input parameters to the method, all of which are required:
*
* $_data -- the data payload as received by the broker in associative array format
* $_meta -- the meta payload as received by the broker in associative array format
* $_where -- string (use the system constant, please) that defines the collection destination
*
* first thing we do is set the collection destination by passing the $_where input parameter to the
* private setCollection() method.
*
* if we (self) are not available, then return immediately where the calling client should assume that the
* logging services are not available and post the necessary console message.
*
* Validate the $_data payload by assigning the contents, filtering the payload through a validation array,
* into a temp variable...
*
* next, insert the generated sequence key into the temp array structure and add the created-date timestamp...
*
* finally, insert the record into the designated collection, trapping any nosql exception raised in our fatal
* handler so that the (error) results are saved to the console log.
*
* @author mike@givingassistant.org
* @version 1.0
*
* @param bool $_im -- is Metric -- should only be set to true from adminIn broker event call
* @throws Exception
*
* HISTORY:
* ========
* 06-07-17 mks original coding
* 06-14-17 mks refactored for dynamodb
* 07-05-17 mks CORE-463: refactored for RMQ and mongoDB
* 07-07-17 mks CORE-463: switch collections on-the-fly for adminIn Metrics event call
* 12-06-17 mks CORE-591: caching log messages based on XML config params, w/console logging on errors
* 01-22-18 mks _INF-139: fixed bug where when caching is disabled, the current error wasn't being
* added to the error stack.
* 03-01-18 mks CORE-689: removed env tag from collection name
* 07-30-18 mks CORE-774: converted to PHP7.2 typeError trapping/processing
*
*/
public function writeLogMessage(bool $_im = false)
{
// if the logger service is unavailable or we don't have a message to publish, then return
if (!$this->available or empty($this->errStack)) return;
$this->status = false;
$oe = $oc = $os = '';
$maxMsgCount = gasConfig::$settings[CONFIG_CACHE][CONFIG_CACHE_LOG_BUFFER_COUNT];
$msgBufferOn = boolval(gasConfig::$settings[CONFIG_CACHE][CONFIG_CACHE_LOG_BUFFER]);
$whichBuffer = ($this->isMetric) ? CONFIG_CACHE_METRICS_BUFFER : CONFIG_CACHE_LOG_BUFFER;
$whichBufferCounter = ($this->isMetric) ? CONFIG_CACHE_METRICS_BUFFER_COUNT : CONFIG_CACHE_LOG_BUFFER_COUNT;
// if (empty($aryData[DB_PKEY])) {
// $this->errStack[(DB_PKEY . $this->ext)] = guid();
// }
// $this->errStack[(LOG_CREATED . $this->ext)] = time();
// admin service is remote - either cache or publish the message
if ($this->publishMessage) {
try {
$currMsgCount = gasCache::sysGet($whichBufferCounter);
$msgBuffer = gasCache::sysGet($whichBuffer);
// remove cache data
gasCache::sysDel($whichBuffer);
gasCache::sysDel($whichBufferCounter);
} catch (Throwable $t) {
$msg = sprintf(INFO_LOC, basename(__FILE__), __LINE__) . ERROR_THROWABLE_EXCEPTION . COLON . $t->getMessage();
consoleLog($this->res, CON_ERROR, $msg);
return;
}
// validate the message buffer fetched from cache
if (!empty($msgBuffer) and !is_array($msgBuffer)) {
$msg = basename(__FILE__) . COLON . __LINE__ . COLON;
$msg .= sprintf(ERROR_CACHE_DATA_MALFORMED, 'array', CONFIG_CACHE_LOG_BUFFER, gettype($msgBuffer));
$msg .= PHP_EOL . 'Dump: ' . PHP_EOL;
$msg .= var_export($msgBuffer, true);
$msg .= PHP_EOL;
$this->throwFatal(basename(__METHOD__) . AT . __LINE__ . COLON . $msg);
return;
}
if ($currMsgCount === false) {
/** @noinspection PhpUnusedLocalVariableInspection */
$currMsgCount = 0;
}
if (false === $msgBuffer) $msgBuffer = [];
$msgBuffer = [...$msgBuffer, ...$this->errStack];
$currMsgCount = count($msgBuffer);
// determine if we're going to publish or cache the message buffer
$publish = (!$msgBufferOn or $currMsgCount >= $maxMsgCount) ? true : false;
if ($publish) {
try {
// $this->abc = new gacAdminClientIn(__METHOD__ . COLON . __LINE__);
$this->abc = new gacLogClient();
if (!$this->abc->status) {
$hdr = basename(__METHOD__) . AT . __LINE__ . COLON;
$msg = ERROR_FAILED_TO_INSTANTIATE . RESOURCE_ADMIN_CLIENT;
consoleLog($this->res, CON_ERROR, $hdr . $msg);
return;
}
} catch (Throwable $t) {
$msg = sprintf(INFO_LOC, basename(__FILE__), __LINE__) . ERROR_THROWABLE_EXCEPTION . COLON . $t->getMessage();
consoleLog($this->res, CON_ERROR, $msg);
return;
}
$request = [
BROKER_REQUEST => ($this->isMetric) ? BROKER_REQUEST_MET : BROKER_REQUEST_LOG,
BROKER_DATA => $msgBuffer,
BROKER_META_DATA => [
META_TEMPLATE => ($this->isMetric) ? TEMPLATE_CLASS_METRICS : TEMPLATE_CLASS_LOGS,
META_CLIENT => CLIENT_SYSTEM
]
];
if (!empty($this->eventGUID)) $request[BROKER_META_DATA][META_EVENT_GUID] = $this->eventGUID;
try {
$route = (!$this->isMetric) ? EXCHANGE_SOURCE_LOGS : EXCHANGE_SOURCE_METRICS;
$this->abc->call(gzcompress(json_encode($request)), $route);
if (is_object($this->abc)) $this->abc->__destruct();
unset($this->abc);
} catch (TypeError | Throwable $t) {
$hdr = basename(__METHOD__) . AT . __LINE__ . COLON;
consoleLog($this->res, CON_ERROR, $hdr . $t->getMessage());
return;
}
unset($this->abc);
// $this->abc = null;
$this->isMetric = false;
// if (gasConfig::$settings[CONFIG_DEBUG]) {
// $msg = sprintf(SUCCESS_CACHE_LOG_DUMP, $currMsgCount);
// consoleLog($this->res, CON_SUCCESS, $msg);
// }
} else {
// update the current message buffer and message buffer counter and re-cache
$msgBuffer = [...$msgBuffer, ...$this->errStack];
$currMsgCount = count($msgBuffer);
try {
if (!gasCache::sysAdd($whichBuffer, $msgBuffer)) {
$this->throwFatal(basename(__METHOD__) . AT . __LINE__ . COLON . ERROR_CACHE_ADD_FAIL . $whichBuffer);
return;
}
if (!gasCache::sysAdd($whichBufferCounter, $currMsgCount)) {
$this->throwFatal(basename(__METHOD__) . AT . __LINE__ . COLON . ERROR_CACHE_ADD_FAIL . $whichBufferCounter . COLON . $currMsgCount);
return;
}
} catch (Throwable $t) {
$msg = sprintf(INFO_LOC, basename(__FILE__), __LINE__) . ERROR_THROWABLE_EXCEPTION . COLON . $t->getMessage();
consoleLog($this->res, CON_ERROR, $msg);
return;
}
}
} else {
// write the message directly to mongodb - start by checking the mongo resource
if (is_null($this->connection)) {
// if we "lost" the resource, attempt to reconnect
$this->connection = gasResourceManager::fetchResource(RESOURCE_MONGO_MASTER, ENV_ADMIN);
// if we can't reconnect, throw a fatal and exit
if (is_null($this->connection)) {
$this->throwFatal(basename(__METHOD__) . AT . __LINE__ . COLON . ERROR_MONGO_CONNECT);
}
}
try {
$record = new MongoDB\Driver\BulkWrite();
foreach ($this->errStack as $errorMessage)
$record->insert($errorMessage);
if ($_im) {
$oc = $this->collectionName;
$oe = $this->ext;
$os = $this->class;
$this->ext = COLLECTION_MONGO_METRICS_EXT;
$this->collectionName = COLLECTION_MONGO_METRICS . $this->ext;
$this->class = COLLECTION_MONGO_METRICS;
} else {
$this->ext = COLLECTION_MONGO_LOGS_EXT;
$this->collectionName = COLLECTION_MONGO_LOGS . $this->ext;
$this->class = COLLECTION_MONGO_LOGS;
}
/** @var WriteResult $result */
$result = $this->connection->executeBulkWrite($this->dbName . DOT . $this->collectionName, $record);
if ($_im) {
$this->ext = $oe;
$this->collectionName = $oc;
$this->class = $os;
}
unset($record);
if ($result->getInsertedCount() != 1) {
$msg = __CLASS__ . COLON . __LINE__ . COLON;
$msg .= sprintf(ERROR_MONGO_INSERT_COUNT, 1, $result->getInsertedCount());
echo getDateTime() . CON_ERROR . $this->res . $msg . PHP_EOL;
// todo -- eventManger should be invoked here
} else {
$this->status = true;
}
} catch (MongoDB\Driver\Exception\BulkWriteException $e) {
$this->throwFatal(basename(__METHOD__) . AT . __LINE__ . COLON . ERROR_MONGO_EXCEPTION_BULK_WRITE . PHP_EOL . $e->getMessage());
} catch (MongoDB\Driver\Exception\InvalidArgumentException $e) {
$this->throwFatal(basename(__METHOD__) . AT . __LINE__ . COLON . ERROR_MONGO_EXCEPTION_INVALID_ARGS . PHP_EOL . $e->getMessage());
} catch (MongoDB\Driver\Exception\ConnectionException $e) {
$this->throwFatal(basename(__METHOD__) . AT . __LINE__ . COLON . ERROR_MONGO_EXCEPTION_CONNECTION . PHP_EOL .$e->getMessage());
} catch (MongoDB\Driver\Exception\RuntimeException $e) {
$this->throwFatal(basename(__METHOD__) . AT . __LINE__ . COLON . ERROR_MONGO_EXCEPTION_RUNTIME . PHP_EOL . $e->getMessage());
}
}
}
/**
* setCollection() -- private method
*
* this is a private method, always called by the writeLogMessage() method, that sets the collection destination
* for the current request. As of this writing, the logger handles all writes to both the log (pgsLogs_log) and
* metrics (pgsMetrics_met) collections. Based on the data passed in the error-message, we set the collection
* destination in this method, along with other member variables that are collection dependent.
*
* the method has a single input parameter, which defaults to a known constant, that is the destination collection.
*
* @author mike@givingassistant.org
* @version 1.0
*
* @param string $_which
* @throws Exception
*
* HISTORY:
* ========
* 06-07-17 mks original coding
* 06-14-17 mks updated for ddb, dynamic environments
* 07-05-17 mks CORE-463: converted to mongodb
* 03-01-18 mks CORE-689: removed env tags from db name
*
*/
private function setCollection(string $_which = TEMPLATE_CLASS_LOGS): void
{
if (!in_array($_which, $this->validTemplates)) {
$this->throwFatal(ERROR_INVALID_TEMPLATE . $_which);
} else {
if ($_which == TEMPLATE_CLASS_LOGS) {
$this->ext = COLLECTION_MONGO_LOGS_EXT;
$this->collectionName = COLLECTION_MONGO_LOGS . $this->ext;
$this->class = COLLECTION_MONGO_LOGS;
} else {
$this->ext = COLLECTION_MONGO_METRICS_EXT;
$this->collectionName = COLLECTION_MONGO_METRICS . $this->ext;
$this->class = COLLECTION_MONGO_METRICS;
}
}
}
/**
* getLog() - public method
*
* getLog is the method that is used to fetch log (or Metrics) records from the mongo collection.
*
* The method has two required parameters:
*
* $_lines - integer value that indicates the number of log entries to retrieve - defaults to the system constant
* $_where - defines which collection to fetch from
*
* Method opens a channel/connection to mongodb and fetches N lines from the collection specified by the
* input parameter.
*
* @author mike@givingassistant.org
* @version 1.0
*
* @param int $_lines
* @param string $_where
* @return null|string
* @throws Exception
*
* HISTORY:
* ========
* 07-05-17 mks CORE-463: original coding
* 09-08-17 mks CORE-529: added event guids to the generated output for dumper
* 07-30-18 mks CORE-774: PHP7.2 Exception Compliance
*
*/
public function getLog($_lines, $_where): ?string
{
if (!in_array($_where, $this->validTemplates)) {
$msg = ERROR_MONGO_TEMPLATE_INVALID . $_where;
return($msg);
}
try {
$this->setCollection($_where);
} catch (Throwable $t) {
consoleLog($this->res, CON_ERROR, ERROR_THROWABLE_EXCEPTION . COLON . $t->getMessage());
}
if (!$this->available) {
return(null); // returning on false implicitly generates a console error message by the calling client
}
if (!is_numeric($_lines) or $_lines < 0) {
$_lines = intval(MONGO_LOG_MAX_LINES);
} else {
$_lines = intval($_lines);
}
$mongoData = null;
$returnData = null;
$cursor = null;
try {
$options = [
STRING_SORT => [(LOG_CREATED . $this->ext) => -1],
STRING_LIMIT => $_lines
];
$filter = [];
$nameSpace = $this->dbName . DOT . $this->collectionName;
$readPreference = new MongoDB\Driver\ReadPreference($this->config[CONFIG_DATABASE_MONGODB_ADMIN][CONFIG_DATABASE_MONGODB_SECONDARY_RP]);
$query = new MongoDB\Driver\Query($filter, $options);
$cursor = $this->connection->executeQuery($nameSpace, $query, $readPreference);
} catch (Throwable | TypeError $e) {
$this->throwFatal(__FILE__ . COLON . __LINE__ . COLON . ERROR_MONGO_EXCEPTION_INVALID_ARGS . PHP_EOL . $e->getMessage());
}
if (!is_null($cursor)) {
foreach ($cursor as $property) {
$property = (array) $property;
$returnData .= '