127 lines
3.4 KiB
PHP
127 lines
3.4 KiB
PHP
<?php
|
|
|
|
class DeepLogger
|
|
{
|
|
private $logFile;
|
|
private static $currentUuid;
|
|
private static $callDepth = 0;
|
|
|
|
public function __construct($logFile = 'function_calls.log')
|
|
{
|
|
$this->logFile = $logFile;
|
|
}
|
|
|
|
public function wrap($instance)
|
|
{
|
|
$handler = $this;
|
|
$class = new ReflectionClass($instance);
|
|
|
|
foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
|
|
if ($method->isConstructor() || $method->isStatic()) continue;
|
|
|
|
$methodName = $method->getName();
|
|
$instance->$methodName = function(...$args) use ($handler, $instance, $methodName) {
|
|
return $handler->logCall($instance, $methodName, $args);
|
|
};
|
|
}
|
|
|
|
return $instance;
|
|
}
|
|
|
|
public function logCall($instance, $method, $args)
|
|
{
|
|
$isRootCall = (self::$callDepth === 0);
|
|
if ($isRootCall) {
|
|
self::$currentUuid = $this->generateUuid();
|
|
}
|
|
self::$callDepth++;
|
|
|
|
$reflection = new ReflectionMethod($instance, $method);
|
|
|
|
// Log IN
|
|
$this->writeLog([
|
|
'timestamp' => date('Y-m-d H:i:s'),
|
|
'uuid' => self::$currentUuid,
|
|
'direction' => 'IN',
|
|
'function' => get_class($instance) . '::' . $method,
|
|
'line' => $reflection->getStartLine(),
|
|
'params' => $this->getParameterValues($reflection, $args)
|
|
]);
|
|
|
|
try {
|
|
$result = $reflection->invokeArgs($instance, $args);
|
|
|
|
// Log OUT
|
|
$this->writeLog([
|
|
'timestamp' => date('Y-m-d H:i:s'),
|
|
'uuid' => self::$currentUuid,
|
|
'direction' => 'OUT',
|
|
'function' => get_class($instance) . '::' . $method,
|
|
'line' => $reflection->getEndLine(),
|
|
'result' => $result
|
|
]);
|
|
|
|
return $result;
|
|
} finally {
|
|
self::$callDepth--;
|
|
if ($isRootCall) {
|
|
self::$currentUuid = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
private function getParameterValues($reflection, $args)
|
|
{
|
|
$params = [];
|
|
foreach ($reflection->getParameters() as $i => $param) {
|
|
$params[$param->name] = $args[$i] ?? ($param->isDefaultValueAvailable()
|
|
? $param->getDefaultValue()
|
|
: null);
|
|
}
|
|
return $params;
|
|
}
|
|
|
|
private function writeLog($data)
|
|
{
|
|
file_put_contents($this->logFile, json_encode($data) . PHP_EOL, FILE_APPEND);
|
|
}
|
|
|
|
private function generateUuid()
|
|
{
|
|
return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
|
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
|
|
mt_rand(0, 0xffff),
|
|
mt_rand(0, 0x0fff) | 0x4000,
|
|
mt_rand(0, 0x3fff) | 0x8000,
|
|
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
|
|
);
|
|
}
|
|
}
|
|
|
|
class TestBusinessController
|
|
{
|
|
public function a($a = 10)
|
|
{
|
|
$r = $this->b(50, $a);
|
|
return json_encode(['a' => $r]);
|
|
}
|
|
|
|
public function b($x, $y)
|
|
{
|
|
$r = $this->c($x + $y);
|
|
return $r;
|
|
}
|
|
|
|
public function c($x)
|
|
{
|
|
return $x * 2;
|
|
}
|
|
}
|
|
|
|
// Usage:
|
|
$logger = new DeepLogger();
|
|
$controller = new TestBusinessController();
|
|
$loggedController = $logger->wrap($controller);
|
|
|
|
// This will now log all calls (a, b, and c)
|
|
echo $loggedController->a(10); |