178 lines
5.7 KiB
PHP
178 lines
5.7 KiB
PHP
<?php
|
|
if (!defined("_PS_VERSION_")) {
|
|
exit();
|
|
}
|
|
|
|
class EcomZoneLogger
|
|
{
|
|
const LOG_FILE = 'ecomzone.log';
|
|
|
|
// Log levels with corresponding severity
|
|
const LEVELS = [
|
|
'DEBUG' => 1,
|
|
'INFO' => 2,
|
|
'WARNING' => 3,
|
|
'ERROR' => 4,
|
|
'CRITICAL' => 5
|
|
];
|
|
|
|
// Current log level - can be changed through configuration
|
|
private static function getLogLevel()
|
|
{
|
|
$configLevel = Configuration::get('ECOMZONE_LOG_LEVEL', 'INFO');
|
|
return isset(self::LEVELS[$configLevel]) ? $configLevel : 'INFO';
|
|
}
|
|
|
|
public static function log($message, $level = 'INFO', $context = [])
|
|
{
|
|
try {
|
|
// Check if we should log this level
|
|
$logLevel = self::getLogLevel();
|
|
if (self::LEVELS[$level] < self::LEVELS[$logLevel]) {
|
|
return true; // Skip logging for less severe levels
|
|
}
|
|
|
|
// Ensure the log directory exists
|
|
$logDir = _PS_MODULE_DIR_ . 'ecomzone/log';
|
|
if (!is_dir($logDir)) {
|
|
if (!@mkdir($logDir, 0755, true)) {
|
|
throw new Exception("Failed to create log directory: " . $logDir);
|
|
}
|
|
@chmod($logDir, 0755); // Ensure the directory is writable
|
|
}
|
|
|
|
// Format the log entry
|
|
$logEntry = [
|
|
'timestamp' => date('Y-m-d H:i:s'),
|
|
'level' => strtoupper($level),
|
|
'message' => $message,
|
|
'context' => $context
|
|
];
|
|
|
|
// For errors and critical issues, also include a stack trace
|
|
if (in_array($level, ['ERROR', 'CRITICAL']) && !isset($context['trace'])) {
|
|
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
|
|
$logEntry['trace'] = array_slice($trace, 1); // Skip the log function itself
|
|
}
|
|
|
|
$logLine = json_encode($logEntry) . PHP_EOL;
|
|
|
|
// Rotate log file if it's too large (> 10MB)
|
|
$logFile = $logDir . '/' . self::LOG_FILE;
|
|
if (file_exists($logFile) && filesize($logFile) > 10 * 1024 * 1024) {
|
|
self::rotateLogFile($logFile);
|
|
}
|
|
|
|
// Write to log file with exclusive lock
|
|
if (!@file_put_contents($logFile, $logLine, FILE_APPEND | LOCK_EX)) {
|
|
throw new Exception("Failed to write to log file: " . $logFile);
|
|
}
|
|
|
|
// Also write to PrestaShop log for error/critical levels
|
|
if (in_array($level, ['ERROR', 'CRITICAL'])) {
|
|
$psLogLevel = ($level === 'ERROR') ? 3 : 4;
|
|
$contextStr = json_encode($context);
|
|
PrestaShopLogger::addLog(
|
|
"EcomZone: {$message} - Context: {$contextStr}",
|
|
$psLogLevel,
|
|
null,
|
|
'EcomZone'
|
|
);
|
|
}
|
|
|
|
return true;
|
|
} catch (Exception $e) {
|
|
// Last resort logging to PHP error log
|
|
error_log('EcomZone logging error: ' . $e->getMessage() .
|
|
'. Original message: ' . $message);
|
|
|
|
// Try to log to PrestaShop's log
|
|
try {
|
|
PrestaShopLogger::addLog(
|
|
'EcomZone logging error: ' . $e->getMessage() . '. Original message: ' . $message,
|
|
3, // Error level
|
|
null,
|
|
'EcomZone'
|
|
);
|
|
} catch (Exception $innerEx) {
|
|
error_log('Failed to log to PrestaShop: ' . $innerEx->getMessage());
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static function rotateLogFile($logFile)
|
|
{
|
|
try {
|
|
$backup = $logFile . '.' . date('Y-m-d-H-i-s') . '.bak';
|
|
if (!@rename($logFile, $backup)) {
|
|
throw new Exception("Failed to rotate log file");
|
|
}
|
|
|
|
// Keep only last 5 backup files
|
|
$backups = glob($logFile . '.*.bak');
|
|
if (count($backups) > 5) {
|
|
usort($backups, function($a, $b) {
|
|
return filemtime($b) - filemtime($a);
|
|
});
|
|
|
|
$toDelete = array_slice($backups, 5);
|
|
foreach ($toDelete as $file) {
|
|
@unlink($file);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
} catch (Exception $e) {
|
|
error_log('EcomZone log rotation error: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static function getLogPath()
|
|
{
|
|
// When running in standalone mode, use the local directory
|
|
if (!defined('_PS_MODULE_DIR_') || !file_exists(_PS_MODULE_DIR_ . 'ecomzone')) {
|
|
return __DIR__ . '/../log/' . self::LOG_FILE;
|
|
}
|
|
|
|
return _PS_MODULE_DIR_ . 'ecomzone/log/' . self::LOG_FILE;
|
|
}
|
|
|
|
public static function getLogContents($maxLines = 100)
|
|
{
|
|
$logFile = self::getLogPath();
|
|
if (!file_exists($logFile)) {
|
|
return [];
|
|
}
|
|
|
|
$logs = [];
|
|
$lines = array_reverse(file($logFile));
|
|
$count = 0;
|
|
|
|
foreach ($lines as $line) {
|
|
if ($count >= $maxLines) break;
|
|
|
|
$entry = json_decode($line, true);
|
|
if ($entry) {
|
|
$logs[] = $entry;
|
|
$count++;
|
|
}
|
|
}
|
|
|
|
return $logs;
|
|
}
|
|
|
|
public static function clearLogs()
|
|
{
|
|
$logFile = self::getLogPath();
|
|
if (file_exists($logFile)) {
|
|
@unlink($logFile);
|
|
self::log("Log file cleared", "INFO");
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|