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