Improved backtracing

This commit is contained in:
Netkas 2022-12-31 01:23:30 -05:00
parent 09141f3d10
commit cdf3eae890
7 changed files with 192 additions and 90 deletions

View file

@ -108,15 +108,14 @@
if(Validate::checkLevelType(LevelType::Verbose, Log::getRuntimeOptions()->getLogLevel())) if(Validate::checkLevelType(LevelType::Verbose, Log::getRuntimeOptions()->getLogLevel()))
{ {
$backtrace_output = Utilities::parseBacktrace($event); $backtrace_output = Utilities::getTraceString($event, Log::getRuntimeOptions()->isDisplayAnsi());
print(sprintf( print(sprintf(
"%s [%s] [%s] (%s) - %s" . PHP_EOL, "%s [%s] [%s] %s %s" . PHP_EOL,
$event->getTimestamp(), $event->getTimestamp(),
self::formatAppColor($options->getApplicationName()), self::formatAppColor($options->getApplicationName()),
self::colorize($event, $event->Level), self::colorize($event, $event->Level),
$backtrace_output !== null ? $backtrace_output : 'λ', $backtrace_output, $event->Message
$event->Message
)); ));
if($event->Exception !== null) if($event->Exception !== null)
@ -126,7 +125,7 @@
} }
print(sprintf( print(sprintf(
"%s [%s] [%s] - %s" . PHP_EOL, "%s [%s] [%s] %s" . PHP_EOL,
$event->getTimestamp(), $event->getTimestamp(),
self::formatAppColor($options->getApplicationName()), self::formatAppColor($options->getApplicationName()),
self::colorize($event, $event->Level), self::colorize($event, $event->Level),

View file

@ -21,14 +21,11 @@
*/ */
public static function out(Options $options, Event $event, ?FileHandle $fileHandle=null): void public static function out(Options $options, Event $event, ?FileHandle $fileHandle=null): void
{ {
$backtrace_output = Utilities::parseBacktrace($event); $backtrace_output = Utilities::getTraceString($event);
$handle = $fileHandle ?? $options->getFileHandle(); $handle = $fileHandle ?? $options->getFileHandle();
switch($event->Level) switch($event->Level)
{ {
// Only process Debug/Verbose events if the log level is set to Debug/Verbose
// otherwise omit it because it could be a performance hit if there are a lot of
// debug/verbose events being logged.
case LevelType::Debug: case LevelType::Debug:
case LevelType::Verbose: case LevelType::Verbose:
if(!Validate::checkLevelType($event->Level, Log::getRuntimeOptions()->getLogLevel())) if(!Validate::checkLevelType($event->Level, Log::getRuntimeOptions()->getLogLevel()))
@ -40,7 +37,7 @@
} }
$handle->fwrite(sprintf( $handle->fwrite(sprintf(
"%s [%s] [%s] (%s) - %s" . PHP_EOL, "%s [%s] [%s] (%s) %s" . PHP_EOL,
$event->getTimestamp(), $event->getTimestamp(),
$options->getApplicationName(), $options->getApplicationName(),
Utilities::levelToString($event->Level), Utilities::levelToString($event->Level),

View file

@ -6,17 +6,16 @@
use LogLib\Objects\Backtrace; use LogLib\Objects\Backtrace;
use LogLib\Objects\Event; use LogLib\Objects\Event;
use OptsLib\Parse; use OptsLib\Parse;
use Properties\Prop;
use Throwable;
class Utilities class Utilities
{ {
/** /**
* Returns the current backtrace * Returns the current backtrace
* *
* @return Backtrace[] * @param bool $full
* @return array
*/ */
public static function getBacktrace(): array public static function getBacktrace(bool $full=false): array
{ {
if(!function_exists('debug_backtrace')) if(!function_exists('debug_backtrace'))
return []; return [];
@ -26,31 +25,10 @@
foreach($backtrace as $trace) foreach($backtrace as $trace)
{ {
$results[] = Prop::fromArray($trace); if(isset($trace['class'] ) && str_contains($trace['class'], 'LogLib') && !$full)
} continue;
return $results; $results[] = new Backtrace($trace);
}
/**
* @param Throwable $e
* @return array
*/
public static function exceptionToArray(Throwable $e): array
{
$results = [
'hash' => spl_object_hash($e),
'type' => get_class($e),
'message' => $e->getMessage(),
'code' => $e->getCode(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTrace(),
];
if($e->getPrevious() !== null)
{
$results['previous'] = self::exceptionToArray($e->getPrevious());
} }
return $results; return $results;
@ -124,6 +102,7 @@
case 'vrb': case 'vrb':
return LevelType::Verbose; return LevelType::Verbose;
default:
case LevelType::Info: case LevelType::Info:
case 'info': case 'info':
case '4': case '4':
@ -153,9 +132,6 @@
case '0': case '0':
case 'sil': case 'sil':
return LevelType::Silent; return LevelType::Silent;
default:
return LevelType::Info;
} }
} }
@ -202,46 +178,6 @@
return date('Y-m-d') . '.log'; return date('Y-m-d') . '.log';
} }
/**
* Returns the formatted backtrace
*
* @param Event $event
* @return string|null
*/
public static function parseBacktrace(Event $event): ?string
{
$backtrace = null;
if ($event->Backtrace !== null && count($event->Backtrace) > 0)
{
foreach ($event->Backtrace as $item)
{
if ($item->Class !== 'LogLib\\Log')
{
$backtrace = $item;
break;
}
}
}
$backtrace_output = null;
if ($backtrace !== null)
{
if ($backtrace->Class !== null)
{
$backtrace_output = $backtrace->Class . $backtrace->Type . $backtrace->Function . '()';
}
else
{
$backtrace_output = $backtrace->Function . '()';
}
if ($backtrace->Line !== null)
$backtrace_output .= ':' . $backtrace->Line;
}
return $backtrace_output;
}
/** /**
* Returns a random string of characters * Returns a random string of characters
* *
@ -260,4 +196,31 @@
return $randomString; return $randomString;
} }
/**
* @param Event $event
* @param bool $ansi
* @return string|null
*/
public static function getTraceString(Event $event, bool $ansi=false): ?string
{
if($event->getBacktrace() == null)
return 'λ';
$backtrace = $event->getBacktrace()[0];
$function = $backtrace->getFunction();
$class = $backtrace->getClass();
if($ansi)
{
$function = "\033[1;37m$function\033[0m";
$class = "\033[1;37m$class\033[0m";
}
if($class == null)
return "{$function}()";
$type = ($backtrace->getType() == '->' ? '->' : '::');
return "{$class}{$type}{$function}()";
}
} }

View file

@ -8,10 +8,12 @@
use LogLib\Abstracts\LevelType; use LogLib\Abstracts\LevelType;
use LogLib\Classes\Console; use LogLib\Classes\Console;
use LogLib\Classes\FileLogging; use LogLib\Classes\FileLogging;
use LogLib\Classes\Utilities;
use LogLib\Classes\Validate; use LogLib\Classes\Validate;
use LogLib\Objects\Event; use LogLib\Objects\Event;
use LogLib\Objects\Options; use LogLib\Objects\Options;
use LogLib\Objects\RuntimeOptions; use LogLib\Objects\RuntimeOptions;
use Properties\Exceptions\ReconstructException;
use Throwable; use Throwable;
class Log class Log
@ -97,6 +99,7 @@
* @param string|null $message The message of the event * @param string|null $message The message of the event
* @param Throwable|null $throwable The exception that was thrown, if any * @param Throwable|null $throwable The exception that was thrown, if any
* @return void * @return void
* @throws ReconstructException
*/ */
private static function log(string $application_name, string $level=LevelType::Info, ?string $message=null, ?Throwable $throwable=null): void private static function log(string $application_name, string $level=LevelType::Info, ?string $message=null, ?Throwable $throwable=null): void
{ {
@ -115,6 +118,9 @@
$event->Message = $message; $event->Message = $message;
$event->Exception = $throwable; $event->Exception = $throwable;
if($event->getBacktrace() == null)
$event->setBacktrace(Utilities::getBacktrace());
if(self::getRuntimeOptions()->isConsoleOutput()) if(self::getRuntimeOptions()->isConsoleOutput())
Console::out($application, $event); Console::out($application, $event);

View file

@ -12,7 +12,7 @@
* @var string|null * @var string|null
* @property_name function * @property_name function
*/ */
public $Function; private $Function;
/** /**
* The line number of the backtrace * The line number of the backtrace
@ -20,7 +20,7 @@
* @var int|null * @var int|null
* @property_name line * @property_name line
*/ */
public $Line; private $Line;
/** /**
* The file name of the backtrace * The file name of the backtrace
@ -28,7 +28,7 @@
* @var string|null * @var string|null
* @property_name file * @property_name file
*/ */
public $File; private $File;
/** /**
* The class name, if any, of the backtrace * The class name, if any, of the backtrace
@ -36,7 +36,7 @@
* @var string|null * @var string|null
* @property_name class * @property_name class
*/ */
public $Class; private $Class;
/** /**
* The current call type. If a method call, "->" is returned. * The current call type. If a method call, "->" is returned.
@ -47,7 +47,7 @@
* @var string|null * @var string|null
* @property_name type * @property_name type
*/ */
public $Type; private $Type;
/** /**
* If inside a function, this lists the functions arguments. If inside * If inside a function, this lists the functions arguments. If inside
@ -56,5 +56,119 @@
* @var array|null * @var array|null
* @property_name args * @property_name args
*/ */
public $Args; private $Args;
/**
* Public Constructor
*
* @param array|null $backtrace
*/
public function __construct(?array $backtrace=null)
{
if($backtrace === null)
return;
$this->Function = $backtrace['function'] ?? null;
$this->Line = $backtrace['line'] ?? null;
$this->File = $backtrace['file'] ?? null;
$this->Class = $backtrace['class'] ?? null;
$this->Type = $backtrace['type'] ?? null;
$this->Args = $backtrace['args'] ?? null;
}
/**
* @return string|null
*/
public function getFunction(): ?string
{
return $this->Function;
}
/**
* @param string|null $Function
*/
public function setFunction(?string $Function): void
{
$this->Function = $Function;
}
/**
* @return int|null
*/
public function getLine(): ?int
{
return $this->Line;
}
/**
* @param int|null $Line
*/
public function setLine(?int $Line): void
{
$this->Line = $Line;
}
/**
* @return string|null
*/
public function getFile(): ?string
{
return $this->File;
}
/**
* @param string|null $File
*/
public function setFile(?string $File): void
{
$this->File = $File;
}
/**
* @return string|null
*/
public function getClass(): ?string
{
return $this->Class;
}
/**
* @param string|null $Class
*/
public function setClass(?string $Class): void
{
$this->Class = $Class;
}
/**
* @return string|null
*/
public function getType(): ?string
{
return $this->Type;
}
/**
* @param string|null $Type
*/
public function setType(?string $Type): void
{
$this->Type = $Type;
}
/**
* @return array|null
*/
public function getArgs(): ?array
{
return $this->Args;
}
/**
* @param array|null $Args
*/
public function setArgs(?array $Args): void
{
$this->Args = $Args;
}
} }

View file

@ -7,7 +7,6 @@
use LogLib\Abstracts\LevelType; use LogLib\Abstracts\LevelType;
use LogLib\Classes\Utilities; use LogLib\Classes\Utilities;
use Throwable; use Throwable;
class Event class Event
{ {
/** /**
@ -33,7 +32,7 @@
* @var Backtrace[]|null * @var Backtrace[]|null
* @property_name backtrace * @property_name backtrace
*/ */
public $Backtrace; private $Backtrace;
/** /**
* The exception that was thrown, if any * The exception that was thrown, if any
@ -53,7 +52,7 @@
public function __construct() public function __construct()
{ {
$this->Timestamp = date('Y-m-dTH:i:s.v') . (date('p') == 'Z' ? 'Z' : 'L'); $this->Timestamp = date('c');
} }
/** /**
@ -75,4 +74,20 @@
return $this->Timestamp; return $this->Timestamp;
} }
/**
* @return array|null
*/
public function getBacktrace(): ?array
{
return $this->Backtrace;
}
/**
* @param array|null $Backtrace
*/
public function setBacktrace(?array $Backtrace): void
{
$this->Backtrace = $Backtrace;
}
} }

8
tests/test_backtrace.php Normal file
View file

@ -0,0 +1,8 @@
<?php
require('ncc');
import('net.nosial.loglib', 'latest');
var_dump(\LogLib\Classes\Utilities::getBacktrace(true));