PNG  IHDR* pHYs+ IDATx]n#; cdLb Ǚ[at¤_:uP}>!Usă cag޿ ֵNu`ݼTâabO7uL&y^wFٝA"l[|ŲHLN밪4*sG3|Dv}?+y߉{OuOAt4Jj.u]Gz*҉sP'VQKbA1u\`& Af;HWj hsO;ogTu uj7S3/QzUr&wS`M$X_L7r2;aE+ώ%vikDA:dR+%KzƉo>eOth$z%: :{WwaQ:wz%4foɹE[9<]#ERINƻv溂E%P1i01 |Jvҗ&{b?9g=^wζXn/lK::90KwrюO\!ջ3uzuGv^;騢wq<Iatv09:tt~hEG`v;3@MNZD.1]L:{ծI3`L(÷ba")Y.iljCɄae#I"1 `3*Bdz>j<fU40⨬%O$3cGt]j%Fߠ_twJ;ABU8vP3uEԑwQ V:h%))LfraqX-ۿX]v-\9I gl8tzX ]ecm)-cgʒ#Uw=Wlێn(0hPP/ӨtQ“&J35 $=]r1{tLuǮ*i0_;NƝ8;-vݏr8+U-kruȕYr0RnC]*ެ(M:]gE;{]tg(#ZJ9y>utRDRMdr9㪩̞zֹb<ģ&wzJM"iI( .ꮅX)Qw:9,i좜\Ԛi7&N0:asϓc];=ΗOӣ APqz93 y $)A*kVHZwBƺnWNaby>XMN*45~ղM6Nvm;A=jֲ.~1}(9`KJ/V F9[=`~[;sRuk]rєT!)iQO)Y$V ی ۤmzWz5IM Zb )ˆC`6 rRa}qNmUfDsWuˤV{ Pݝ'=Kֳbg,UҘVz2ﴻnjNgBb{? ߮tcsͻQuxVCIY۠:(V뺕 ٥2;t`@Fo{Z9`;]wMzU~%UA蛚dI vGq\r82iu +St`cR.6U/M9IENDB` bool, 'message' => string] */ public static function deleteLogs($date = null) { $logger = self::getInstance(); $deleted = []; $errors = []; if ($date === 'all') { // Tüm log dosyalarını sil $files = glob(self::$logDir . '*.log'); foreach ($files as $file) { if (is_file($file)) { if (@unlink($file)) { $deleted[] = basename($file); } else { $errors[] = basename($file); } } } } elseif ($date) { // Belirli bir tarihin log dosyalarını sil $appLog = self::$logDir . 'app_' . $date . '.log'; $errorLog = self::$logDir . 'errors_' . $date . '.log'; if (file_exists($appLog)) { if (@unlink($appLog)) { $deleted[] = basename($appLog); } else { $errors[] = basename($appLog); } } if (file_exists($errorLog)) { if (@unlink($errorLog)) { $deleted[] = basename($errorLog); } else { $errors[] = basename($errorLog); } } } else { // Bugünün log dosyalarını sil $today = date('Y-m-d'); $appLog = self::$logDir . 'app_' . $today . '.log'; $errorLog = self::$logDir . 'errors_' . $today . '.log'; if (file_exists($appLog)) { if (@unlink($appLog)) { $deleted[] = basename($appLog); } else { $errors[] = basename($appLog); } } if (file_exists($errorLog)) { if (@unlink($errorLog)) { $deleted[] = basename($errorLog); } else { $errors[] = basename($errorLog); } } } if (!empty($errors)) { return [ 'success' => false, 'message' => 'Bazı log dosyaları silinemedi: ' . implode(', ', $errors), 'deleted' => $deleted ]; } if (empty($deleted)) { return [ 'success' => false, 'message' => 'Silinecek log dosyası bulunamadı.' ]; } return [ 'success' => true, 'message' => count($deleted) . ' log dosyası başarıyla silindi: ' . implode(', ', $deleted), 'deleted' => $deleted ]; } /** * Notice logla */ public static function notice($message, $context = []) { self::log(self::NOTICE, $message, $context); } /** * PHP hatalarını yakala */ public static function handleError($errno, $errstr, $errfile, $errline, $errcontext = null) { $level = self::NOTICE; switch ($errno) { case E_ERROR: case E_CORE_ERROR: case E_COMPILE_ERROR: case E_PARSE: $level = self::ERROR; break; case E_WARNING: case E_CORE_WARNING: case E_COMPILE_WARNING: $level = self::WARNING; break; case E_NOTICE: case E_USER_NOTICE: $level = self::NOTICE; break; case E_DEPRECATED: case E_USER_DEPRECATED: $level = self::WARNING; break; } $message = sprintf( "%s in %s on line %d", $errstr, basename($errfile), $errline ); self::log($level, $message, [ 'file' => $errfile, 'line' => $errline, 'errno' => $errno ]); // Kritik hatalar için PHP'nin kendi error handler'ını da çalıştır if ($errno === E_ERROR || $errno === E_CORE_ERROR) { return false; } return true; } /** * Exception yakala */ public static function handleException($exception) { self::error($exception->getMessage(), [ 'file' => $exception->getFile(), 'line' => $exception->getLine(), 'trace' => $exception->getTraceAsString() ]); } /** * Log dosyalarını oku */ public static function getLogs($date = null, $level = null, $limit = 100) { $logger = self::getInstance(); $date = $date ?? date('Y-m-d'); $logFile = self::$logDir . 'app_' . $date . '.log'; if (!file_exists($logFile)) { return []; } $lines = file($logFile, FILE_IGNORE_NEW_LINES | FILE_IGNORE_NEW_LINES); $logs = []; foreach (array_reverse($lines) as $line) { if (empty(trim($line))) continue; // Log satırını parse et - daha esnek regex // Format: [timestamp] [level] [ip] [user] message | URL: url | Context: json if (preg_match('/\[([^\]]+)\] \[([^\]]+)\] \[([^\]]+)\] \[([^\]]+)\] (.+?) \| URL: ([^|]+)( \| Context: (.+))?$/', $line, $matches)) { $logEntry = [ 'timestamp' => trim($matches[1]), 'level' => trim($matches[2]), 'ip' => trim($matches[3]), 'user' => trim($matches[4]), 'message' => trim($matches[5]), 'url' => trim($matches[6]), 'context' => [] ]; // Context varsa parse et if (isset($matches[8]) && !empty(trim($matches[8]))) { $contextJson = trim($matches[8]); $decoded = json_decode($contextJson, true); if (json_last_error() === JSON_ERROR_NONE) { $logEntry['context'] = $decoded; } } // Filtrele if ($level && $logEntry['level'] !== $level) { continue; } $logs[] = $logEntry; if (count($logs) >= $limit) { break; } } else { // Parse edilemeyen satırları da göster (debug için) // error_log("Log parse edilemedi: " . substr($line, 0, 100)); } } return $logs; } /** * Log istatistikleri */ public static function getStats($date = null) { $date = $date ?? date('Y-m-d'); $logFile = self::$logDir . 'app_' . $date . '.log'; if (!file_exists($logFile)) { return [ 'total' => 0, 'errors' => 0, 'warnings' => 0, 'notices' => 0, 'info' => 0, 'by_file' => [], 'by_user' => [] ]; } $lines = file($logFile, FILE_IGNORE_NEW_LINES); $stats = [ 'total' => 0, 'errors' => 0, 'warnings' => 0, 'notices' => 0, 'info' => 0, 'by_file' => [], 'by_user' => [] ]; foreach ($lines as $line) { if (preg_match('/\[([^\]]+)\] \[([^\]]+)\] \[([^\]]+)\] \[([^\]]+)\] (.+?) \| URL: ([^|]+)( \| Context: (.+))?$/', $line, $matches)) { $level = trim($matches[2]); $user = trim($matches[4]); $context = []; // Context varsa parse et if (isset($matches[8]) && !empty(trim($matches[8]))) { $contextJson = trim($matches[8]); $decoded = json_decode($contextJson, true); if (json_last_error() === JSON_ERROR_NONE) { $context = $decoded; } } $stats['total']++; switch ($level) { case self::ERROR: $stats['errors']++; break; case self::WARNING: $stats['warnings']++; break; case self::NOTICE: $stats['notices']++; break; case self::INFO: $stats['info']++; break; } // Dosya bazlı istatistik if (isset($context['file'])) { $file = basename($context['file']); $stats['by_file'][$file] = ($stats['by_file'][$file] ?? 0) + 1; } // Kullanıcı bazlı istatistik $stats['by_user'][$user] = ($stats['by_user'][$user] ?? 0) + 1; } } // En çok hata veren dosyaları sırala arsort($stats['by_file']); arsort($stats['by_user']); return $stats; } } // PHP error handler'ı kaydet (sadece bir kez) if (!function_exists('logger_error_handler_registered')) { set_error_handler(['Logger', 'handleError']); set_exception_handler(['Logger', 'handleException']); function logger_error_handler_registered() { return true; } }