Update Logging Class and add phpunit for Logging Class

Various fixes in the logging class for more clear internal flags setting
and clearn up of complex type checks and debug validation checks.
Add basic debugger logging class phpunit checker (based on debug/print
and only very basic for echo)

Other minor fixes and updates (phpunit with inital dead code check)
This commit is contained in:
Clemens Schwaighofer
2022-02-22 17:56:00 +09:00
parent 0109a67b20
commit 8267bcd8b8
6 changed files with 957 additions and 203 deletions

View File

@@ -87,6 +87,8 @@ $new_log = new CoreLibs\Debug\Logging([
]);
$new_log->debug('OPTIONS TYPE', 'New Type error');
print "OPTIONS LOGGER:<br>" . $new_log->printErrorMsg();
$new_log->setLogLevel('debug', 'on', ['A', 'B', 'C' => false]);
print "LOG LEVEL: " . DebugSupport::printAr($new_log->getLogLevel('debug', 'on')) . "<br>";
echo "<b>CLASS DEBUG CALL</b><br>";

View File

@@ -173,7 +173,7 @@ class Basic
public function basicSetLogId(string $string): string
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use $basic->log->basicSetLogId() or use \CoreLibs\Debug\Logging() class', E_USER_DEPRECATED);
return $this->log->basicSetLogId($string);
return $this->log->setLogId($string);
}
// ****** DEBUG/ERROR FUNCTIONS ******
@@ -263,7 +263,7 @@ class Basic
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use $basic->log->debugFor() or use \CoreLibs\Debug\Logging() class', E_USER_DEPRECATED);
/** @phan-suppress-next-line PhanTypeMismatchArgumentReal, PhanParamTooFew @phpstan-ignore-next-line */
$this->log->debugFor(...[func_get_args()]);
$this->log->setLogLevel(...[func_get_args()]);
}
/**

View File

@@ -361,9 +361,6 @@ class ArrayIO extends \CoreLibs\DB\IO
$this->table_array[$column]['value'] = '';
} else {
if ($this->table_array[$column]['tmp'] != 'none' && $this->table_array[$column]['tmp']) {
// Dateiname zusammenbasteln: org-name + _pkid liste + .ext
list($name, $ext) = explode('.', $this->table_array[$column]['dn']);
// mozilla, patch
$fn_name = explode('/', $this->table_array[$column]['dn']);
$this->table_array[$column]['dn'] = $fn_name[count($fn_name) - 1];

View File

@@ -173,16 +173,17 @@ class Logging
// can be overridden with basicSetLogFileId later
if (!empty($this->options['file_id'])) {
$this->basicSetLogId($this->options['file_id'] ?? '');
$this->setLogId($this->options['file_id'] ?? '');
} elseif (!empty($GLOBALS['LOG_FILE_ID'])) {
// legacy flow, should be removed and only set via options
$this->basicSetLogId($GLOBALS['LOG_FILE_ID']);
$this->setLogId($GLOBALS['LOG_FILE_ID']);
} elseif (defined('LOG_FILE_ID')) {
$this->basicSetLogId(LOG_FILE_ID);
// legacy flow, should be removed and only set via options
$this->setLogId(LOG_FILE_ID);
}
// init the log levels
$this->setLogLevels();
$this->initLogLevels();
}
// *** PRIVATE ***
@@ -192,80 +193,84 @@ class Logging
*
* @return void
*/
private function setLogLevels(): void
private function initLogLevels(): void
{
// if given via parameters, only for all
// globals overrule given settings, for one (array), eg $ECHO['db'] = 1;
if (isset($this->options['debug']) && is_array($this->options['debug'])) {
$this->debug_output = $this->options['debug'];
} elseif (isset($GLOBALS['DEBUG']) && is_array($GLOBALS['DEBUG'])) {
$this->debug_output = $GLOBALS['DEBUG'];
}
if (isset($this->options['echo']) && is_array($this->options['echo'])) {
$this->debug_output = $this->options['echo'];
} elseif (isset($GLOBALS['ECHO']) && is_array($GLOBALS['ECHO'])) {
$this->echo_output = $GLOBALS['ECHO'];
}
if (isset($this->options['print']) && is_array($this->options['print'])) {
$this->debug_output = $this->options['print'];
} elseif (isset($GLOBALS['PRINT']) && is_array($GLOBALS['PRINT'])) {
$this->print_output = $GLOBALS['PRINT'];
}
// exclude these ones from output
if (isset($this->options['debug_not']) && is_array($this->options['debug_not'])) {
$this->debug_output = $this->options['debug_not'];
} elseif (isset($GLOBALS['DEBUG_NOT']) && is_array($GLOBALS['DEBUG_NOT'])) {
$this->debug_output_not = $GLOBALS['DEBUG_NOT'];
}
if (isset($this->options['echo_not']) && is_array($this->options['echo_not'])) {
$this->debug_output = $this->options['echo_not'];
} elseif (isset($GLOBALS['ECHO_NOT']) && is_array($GLOBALS['ECHO_NOT'])) {
$this->echo_output_not = $GLOBALS['ECHO_NOT'];
}
if (isset($this->options['print_not']) && is_array($this->options['print_not'])) {
$this->debug_output = $this->options['print_not'];
} elseif (isset($GLOBALS['PRINT_NOT']) && is_array($GLOBALS['PRINT_NOT'])) {
$this->print_output_not = $GLOBALS['PRINT_NOT'];
foreach (['debug', 'echo', 'print'] as $type) {
// include or exclude (off) from output
foreach (['on', 'off'] as $flag) {
$in_type = $type;
if ($flag == 'off') {
$in_type .= '_not';
}
$up_type = strtoupper($in_type);
if (
isset($this->options[$in_type]) &&
is_array($this->options[$in_type])
) {
$this->setLogLevel($type, $flag, $this->options[$in_type]);
} elseif (
isset($GLOBALS[$up_type]) &&
is_array($GLOBALS[$up_type])
) {
$this->setLogLevel($type, $flag, $GLOBALS[$up_type]);
}
}
}
// all overrule
$this->debug_output_all =
$this->setLogLevelAll(
'debug',
$this->options['debug_all'] ??
$GLOBALS['DEBUG_ALL'] ??
false;
$this->echo_output_all =
$GLOBALS['DEBUG_ALL'] ??
false
);
$this->setLogLevelAll(
'echo',
$this->options['echo_all'] ??
$GLOBALS['ECHO_ALL'] ??
false;
$this->print_output_all =
$GLOBALS['ECHO_ALL'] ??
false
);
$this->setLogLevelAll(
'print',
$this->options['print_all'] ??
$GLOBALS['PRINT_ALL'] ??
false;
$GLOBALS['PRINT_ALL'] ??
false
);
// GLOBAL rules for log writing
$this->log_print_file_date =
$this->setGetLogPrintFileDate(
$this->options['print_file_date'] ??
$GLOBALS['LOG_PRINT_FILE_DATE'] ??
true;
$this->log_per_level =
$GLOBALS['LOG_PRINT_FILE_DATE'] ??
true
);
$this->setLogPer(
'level',
$this->options['per_level'] ??
$GLOBALS['LOG_PER_LEVEL'] ??
false;
$this->log_per_class =
$GLOBALS['LOG_PER_LEVEL'] ??
false
);
$this->setLogPer(
'class',
$this->options['per_class'] ??
$GLOBALS['LOG_PER_CLASS'] ??
false;
$this->log_per_page =
$GLOBALS['LOG_PER_CLASS'] ??
false
);
$this->setLogPer(
'page',
$this->options['per_page'] ??
$GLOBALS['LOG_PER_PAGE'] ??
false;
$this->log_per_run =
$GLOBALS['LOG_PER_PAGE'] ??
false
);
$this->setLogPer(
'run',
$this->options['per_run'] ??
$GLOBALS['LOG_PER_RUN'] ??
false;
$GLOBALS['LOG_PER_RUN'] ??
false
);
// set log per date
if ($this->log_print_file_date) {
if ($this->setGetLogPrintFileDate()) {
$this->log_file_date = date('Y-m-d');
}
// set per run ID
@@ -295,46 +300,14 @@ class Logging
{
$access = false;
// check if we do debug, echo or print
switch ($target) {
case 'debug':
if (
(
(isset($this->debug_output[$level]) && $this->debug_output[$level]) ||
$this->debug_output_all
) &&
(!isset($this->debug_output_not[$level]) ||
(isset($this->debug_output_not[$level]) && !$this->debug_output_not[$level])
)
) {
$access = true;
}
break;
case 'echo':
if (
(
(isset($this->echo_output[$level]) && $this->echo_output[$level]) ||
$this->echo_output_all
) &&
(!isset($this->echo_output_not[$level]) ||
(isset($this->echo_output_not[$level]) && !$this->echo_output_not[$level])
)
) {
$access = true;
}
break;
case 'print':
if (
(
(isset($this->print_output[$level]) && $this->print_output[$level]) ||
$this->print_output_all
) &&
(!isset($this->print_output_not[$level]) ||
(isset($this->print_output_not[$level]) && !$this->print_output_not[$level])
)
) {
$access = true;
}
break;
if (
(
$this->getLogLevel($target, 'on', $level) ||
$this->getLogLevelAll($target)
) &&
!$this->getLogLevel($target, 'off', $level)
) {
$access = true;
}
return $access;
}
@@ -355,8 +328,6 @@ class Logging
return false;
}
// init output variable
$output = $error_string; // output formated error string to output file
// init base file path
$fn = $this->log_folder . $this->log_print_file . '.' . $this->log_file_name_ext;
// log ID prefix settings, if not valid, replace with empty
@@ -369,8 +340,10 @@ class Logging
if ($this->log_per_run) {
$rpl_string = '_' . $this->log_file_unique_id; // add 8 char unique string
} elseif ($this->log_print_file_date) {
} elseif ($this->setGetLogPrintFileDate()) {
$rpl_string = '_' . $this->log_file_date; // add date to file
} else {
$rpl_string = '';
}
$fn = str_replace('##DATE##', $rpl_string, $fn); // create output filename
@@ -397,12 +370,13 @@ class Logging
$this->log_file_name = $fn;
$fp = fopen($this->log_file_name, 'a');
if ($fp !== false) {
fwrite($fp, $output);
fwrite($fp, $error_string);
fclose($fp);
return true;
} else {
echo "<!-- could not open file: " . $this->log_file_name . " //-->";
return false;
}
return true;
}
// *** PUBLIC ***
@@ -424,8 +398,21 @@ class Logging
* if non valid string is given it returns the previous set one only
* @param string $string log file id string value
* @return string returns the set log file id string
* @deprecated Use $log->setLogId()
*/
public function basicSetLogId(string $string): string
{
return $this->setLogId($string);
}
/**
* sets the internal log file prefix id
* string must be a alphanumeric string
* if non valid string is given it returns the previous set one only
* @param string $string log file id string value
* @return string returns the set log file id string
*/
public function setLogId(string $string): string
{
if (preg_match("/^[\w\-]+$/", $string)) {
$this->log_file_id = $string;
@@ -448,6 +435,7 @@ class Logging
* @param string $flag on/off
* array $array of levels to turn on/off debug
* @return bool Return false if type or flag is invalid
* @deprecated Use setLogLevel
*/
public function debugFor(string $type, string $flag): bool
{
@@ -489,13 +477,15 @@ class Logging
/**
* passes list of level names, to turn on debug
* eg $foo->debugFor('print', 'on', ['LOG', 'DEBUG', 'INFO']);
* TODO: currently we can only turn ON
* @param string $type debug, echo, print
* @param string $flag on/off
* array $array of levels to turn on/off debug
* @return bool Return false if type or falg invalid
* @param string $type debug, echo, print
* @param string $flag on/off
* @param array<mixed> $debug_on Array of levels to turn on/off debug
* To turn off a level set 'Level' => false,
* If not set, switches to on
* @return bool Return false if type or flag invalid
* also false if debug array is empty
*/
public function setLogLevel(string $type, string $flag): bool
public function setLogLevel(string $type, string $flag, array $debug_on): bool
{
// abort if not valid type
if (!in_array($type, ['debug', 'echo', 'print'])) {
@@ -505,14 +495,17 @@ class Logging
if (!in_array($flag, ['on', 'off'])) {
return false;
}
$debug_on = func_get_args();
array_shift($debug_on); // kick out type
array_shift($debug_on); // kick out flag (on/off)
if (count($debug_on) >= 1) {
foreach ($debug_on as $level) {
foreach ($debug_on as $level => $set) {
$switch = $type . '_output' . ($flag == 'off' ? '_not' : '');
$this->{$switch}[$level] = true;
if (!is_bool($set)) {
$level = $set;
$set = true;
}
$this->{$switch}[$level] = $set;
}
} else {
return false;
}
return true;
}
@@ -536,8 +529,8 @@ class Logging
return false;
}
$switch = $type . '_output' . ($flag == 'off' ? '_not' : '');
// bool
if ($level !== null) {
// log level direct check must be not null or not empty string
if (!empty($level)) {
return $this->{$switch}[$level] ?? false;
}
// array
@@ -576,6 +569,30 @@ class Logging
return $this->{'log_per_' . $type};
}
/**
* Set or get the log file date extension flag
* if null or empty parameter gets current flag
* @param boolean|null $set Set the date suffix for log files
* If set to null return current set
* @return boolean Current set flag
*/
public function setGetLogPrintFileDate(?bool $set = null): bool
{
if ($set !== null) {
$this->log_print_file_date = $set;
}
return $this->log_print_file_date;
}
/**
* Return current set log file name
* @return string Filename set set after the last time debug was called
*/
public function getLogFileName(): string
{
return $this->log_file_name;
}
/**
* A replacement for the \CoreLibs\Debug\Support::printAr
* But this does not wrap it in <pre></pre>
@@ -602,10 +619,23 @@ class Logging
* if strip is false, recommended to add that to $string
* @return bool True if logged, false if not logged
*/
public function debug(string $level, string $string, bool $strip = false, string $prefix = ''): bool
{
if (!$this->doDebugTrigger('debug', $level)) {
return false;
public function debug(
string $level,
string $string,
bool $strip = false,
string $prefix = ''
): bool {
$status = false;
// must be debug on and either echo or print on
if (
!$this->doDebugTrigger('debug', $level) ||
(
// if debug is on, either print or echo must be set to on
!$this->doDebugTrigger('print', $level) &&
!$this->doDebugTrigger('echo', $level)
)
) {
return $status;
}
// get the last class entry and wrie that
$class = Support::getCallerClass();
@@ -613,7 +643,7 @@ class Logging
$timestamp = Support::printTime();
// same string put for print (no html data inside)
// write to file if set
$this->writeErrorMsg(
$status = $this->writeErrorMsg(
$level,
'[' . $timestamp . '] '
. '[' . $this->host_name . '] '
@@ -662,66 +692,62 @@ class Logging
Html::htmlent($string)
)
. "</div><!--#BR#-->";
$status = true;
}
return true;
return $status;
}
/**
* merges the given error array with the one from this class
* only merges visible ones
* @param array<mixed> $error_msg error array
* @return void has no return
* for ECHO ON only
* returns error data as string so it can be echoed out
* @param string $header_prefix prefix string for header
* @return string error msg for all levels
*/
public function mergeErrors(array $error_msg = []): void
{
if (!is_array($error_msg)) {
$error_msg = [];
}
array_push($this->error_msg, ...$error_msg);
}
/**
* prints out the error string
* @param string $string prefix string for header
* @return string error msg for all levels
*/
public function printErrorMsg(string $string = ''): string
public function printErrorMsg(string $header_prefix = ''): string
{
$string_output = '';
if ($this->debug_output_all) {
if ($this->error_msg_prefix) {
$string = $this->error_msg_prefix;
}
$script_end = microtime(true) - $this->script_starttime;
foreach ($this->error_msg as $level => $temp_debug_output) {
if ($this->doDebugTrigger('debug', $level)) {
if ($this->doDebugTrigger('echo', $level)) {
$string_output .= '<div style="font-size: 12px;">'
. '[<span style="font-style: italic; color: #c56c00;">' . $level . '</span>] '
. ($string ? "<b>**** " . Html::htmlent($string) . " ****</br>\n" : "")
. '</div>'
. join('', $temp_debug_output);
} // echo it out
} // do printout
} // for each level
// create the output wrapper around, so we have a nice formated output per class
if ($string_output) {
$string_prefix = '<div style="text-align: left; padding: 5px; font-size: 10px; '
. 'font-family: sans-serif; border-top: 1px solid black; '
. 'border-bottom: 1px solid black; margin: 10px 0 10px 0; '
. 'background-color: white; color: black;">'
. '<div style="font-size: 12px;">{<span style="font-style: italic; color: #928100;">'
. Support::getCallerClass() . '</span>}</div>';
$string_output = $string_prefix . $string_output
. '<div><span style="font-style: italic; color: #108db3;">Script Run Time:</span> '
. $script_end . '</div>'
. '</div>';
}
// if not debug && echo on, do not return anything
if (
!$this->getLogLevelAll('debug') ||
!$this->getLogLevelAll('echo')
) {
return $string_output;
}
if ($this->error_msg_prefix) {
$header_prefix = $this->error_msg_prefix;
}
$script_end = microtime(true) - $this->script_starttime;
foreach ($this->error_msg as $level => $temp_debug_output) {
if ($this->doDebugTrigger('debug', $level)) {
if ($this->doDebugTrigger('echo', $level)) {
$string_output .= '<div style="font-size: 12px;">'
. '[<span style="font-style: italic; color: #c56c00;">' . $level . '</span>] '
. ($header_prefix ? "<b>**** " . Html::htmlent($header_prefix) . " ****</br>\n" : '')
. '</div>'
. join('', $temp_debug_output);
} // echo it out
} // do printout
} // for each level
// create the output wrapper around
// so we have a nice formated output per class
if ($string_output) {
$string_prefix = '<div style="text-align: left; padding: 5px; font-size: 10px; '
. 'font-family: sans-serif; border-top: 1px solid black; '
. 'border-bottom: 1px solid black; margin: 10px 0 10px 0; '
. 'background-color: white; color: black;">'
. '<div style="font-size: 12px;">{<span style="font-style: italic; color: #928100;">'
. Support::getCallerClass() . '</span>}</div>';
$string_output = $string_prefix . $string_output
. '<div><span style="font-style: italic; color: #108db3;">Script Run Time:</span> '
. $script_end . '</div>'
. '</div>';
}
// }
return $string_output;
}
/**
* for ECHO ON only
* unsests the error message array
* can be used if writing is primary to file
* if no level given resets all
@@ -738,14 +764,26 @@ class Logging
}
/**
* for ECHO ON only
* Get current error message array
*
* @return array<mixed> error messages collected
*/
public function getErrorMsg(): array
{
return $this->error_msg;
}
/**
* for ECHO ON only
* merges the given error array with the one from this class
* only merges visible ones
* @param array<mixed> $error_msg error array
* @return void has no return
*/
public function mergeErrors(array $error_msg = []): void
{
array_push($this->error_msg, ...$error_msg);
}
}
// __END__