Files
ISP-Billing/system/autoload/CronLog.php
2026-01-16 12:26:30 +01:00

284 lines
7.9 KiB
PHP

<?php
/**
* Cron Logging System
* Tracks cron job execution and performance
*/
class CronLog
{
private static $logId = null;
private static $startTime = null;
private static $startMemory = null;
/**
* Start logging a cron job
* @param string $cronType Type of cron job (main, reminder, etc.)
* @return int Log ID
*/
public static function start($cronType = 'main')
{
self::$startTime = microtime(true);
self::$startMemory = memory_get_usage();
$log = ORM::for_table('tbl_cron_logs')->create();
$log->cron_type = $cronType;
$log->started_at = date('Y-m-d H:i:s');
$log->status = 'running';
$log->save();
self::$logId = $log->id();
return self::$logId;
}
/**
* Update log with current statistics
* @param array $stats Statistics array
*/
public static function updateStats($stats = [])
{
if (!self::$logId) return;
$log = ORM::for_table('tbl_cron_logs')->find_one(self::$logId);
if (!$log) return;
foreach ($stats as $key => $value) {
if (property_exists($log, $key)) {
$log->$key = $value;
}
}
$log->save();
}
/**
* Increment a counter
* @param string $field Field to increment
* @param int $amount Amount to increment by
*/
public static function increment($field, $amount = 1)
{
if (!self::$logId) return;
$log = ORM::for_table('tbl_cron_logs')->find_one(self::$logId);
if (!$log) return;
if (property_exists($log, $field)) {
$log->$field = $log->$field + $amount;
$log->save();
}
}
/**
* Complete the cron job successfully
* @param array $finalStats Final statistics
*/
public static function complete($finalStats = [])
{
if (!self::$logId) return;
$log = ORM::for_table('tbl_cron_logs')->find_one(self::$logId);
if (!$log) return;
$log->finished_at = date('Y-m-d H:i:s');
$log->status = 'completed';
// Calculate execution time
if (self::$startTime) {
$log->execution_time = round(microtime(true) - self::$startTime, 3);
}
// Calculate memory usage
if (self::$startMemory) {
$currentMemory = memory_get_usage();
$peakMemory = memory_get_peak_usage();
$log->memory_usage = self::formatBytes($peakMemory - self::$startMemory);
}
// Update final stats
foreach ($finalStats as $key => $value) {
if (property_exists($log, $key)) {
$log->$key = $value;
}
}
$log->save();
// Clean up old logs (keep last 1000 records)
self::cleanup();
}
/**
* Mark cron job as failed
* @param string $errorMessage Error message
* @param array $finalStats Final statistics
*/
public static function fail($errorMessage, $finalStats = [])
{
if (!self::$logId) return;
$log = ORM::for_table('tbl_cron_logs')->find_one(self::$logId);
if (!$log) return;
$log->finished_at = date('Y-m-d H:i:s');
$log->status = 'failed';
$log->error_message = $errorMessage;
// Calculate execution time
if (self::$startTime) {
$log->execution_time = round(microtime(true) - self::$startTime, 3);
}
// Update final stats
foreach ($finalStats as $key => $value) {
if (property_exists($log, $key)) {
$log->$key = $value;
}
}
$log->save();
}
/**
* Get recent cron logs
* @param int $limit Number of records to return
* @param string $cronType Filter by cron type
* @return array
*/
public static function getRecent($limit = 50, $cronType = null)
{
$query = ORM::for_table('tbl_cron_logs');
if ($cronType) {
$query->where('cron_type', $cronType);
}
return $query->order_by_desc('started_at')
->limit($limit)
->find_many();
}
/**
* Get cron job statistics
* @param int $days Number of days to look back
* @return array
*/
public static function getStats($days = 7)
{
$since = date('Y-m-d H:i:s', strtotime("-$days days"));
$stats = ORM::for_table('tbl_cron_logs')
->where_gte('started_at', $since)
->find_many();
$result = [
'total_runs' => count($stats),
'successful_runs' => 0,
'failed_runs' => 0,
'total_expired_users' => 0,
'total_notifications_sent' => 0,
'total_auto_renewals' => 0,
'avg_execution_time' => 0,
'last_run' => null,
'last_success' => null,
'last_failure' => null
];
$totalExecutionTime = 0;
$executionCount = 0;
foreach ($stats as $log) {
if ($log->status == 'completed') {
$result['successful_runs']++;
$result['last_success'] = $log->finished_at;
} elseif ($log->status == 'failed') {
$result['failed_runs']++;
$result['last_failure'] = $log->finished_at;
}
$result['total_expired_users'] += $log->expired_users_processed;
$result['total_notifications_sent'] += $log->notifications_sent;
$result['total_auto_renewals'] += $log->auto_renewals_successful;
if ($log->execution_time) {
$totalExecutionTime += $log->execution_time;
$executionCount++;
}
if (!$result['last_run'] || $log->started_at > $result['last_run']) {
$result['last_run'] = $log->started_at;
}
}
if ($executionCount > 0) {
$result['avg_execution_time'] = round($totalExecutionTime / $executionCount, 3);
}
return $result;
}
/**
* Clean up old logs (keep last 1000 records)
*/
private static function cleanup()
{
$count = ORM::for_table('tbl_cron_logs')->count();
if ($count > 1000) {
$logsToDelete = ORM::for_table('tbl_cron_logs')
->order_by_asc('started_at')
->limit($count - 1000)
->find_many();
foreach ($logsToDelete as $log) {
$log->delete();
}
}
}
/**
* Format bytes to human readable format
* @param int $bytes
* @return string
*/
private static function formatBytes($bytes)
{
$units = ['B', 'KB', 'MB', 'GB'];
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= pow(1024, $pow);
return round($bytes, 2) . ' ' . $units[$pow];
}
/**
* Check if cron is running (has a running log in last 5 minutes)
* @return bool
*/
public static function isRunning()
{
$fiveMinutesAgo = date('Y-m-d H:i:s', strtotime('-5 minutes'));
$runningLog = ORM::for_table('tbl_cron_logs')
->where('status', 'running')
->where_gte('started_at', $fiveMinutesAgo)
->find_one();
return $runningLog ? true : false;
}
/**
* Get the last successful cron run
* @return object|null
*/
public static function getLastSuccess()
{
return ORM::for_table('tbl_cron_logs')
->where('status', 'completed')
->order_by_desc('finished_at')
->find_one();
}
}