284 lines
7.9 KiB
PHP
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();
|
|
}
|
|
}
|