microtime( true ), 's' => $status, 'u' => mb_substr( (string) $url, 0, 500 ), 'r' => mb_substr( (string) $reason, 0, 255 ), 'ms' => null === $response_time_ms ? null : (int) $response_time_ms, 'rule' => $rule, ) ); $file = trailingslashit( $dir ) . gmdate( 'Y-m-d' ) . '.log'; @file_put_contents( $file, $line . "\n", FILE_APPEND | LOCK_EX ); // phpcs:ignore } public static function recent( $limit = 200, $status_filter = null ) { $dir = self::log_dir(); if ( ! is_dir( $dir ) ) { return array(); } $files = glob( trailingslashit( $dir ) . '*.log' ) ?: array(); rsort( $files ); $rows = array(); foreach ( array_slice( $files, 0, self::RAW_RETENTION_DAYS ) as $file ) { $lines = file( $file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES ) ?: array(); for ( $i = count( $lines ) - 1; $i >= 0 && count( $rows ) < $limit * 4; $i-- ) { $row = json_decode( $lines[ $i ], true ); if ( ! is_array( $row ) ) { continue; } if ( $status_filter && ( $row['s'] ?? '' ) !== $status_filter ) { continue; } $rows[] = $row; if ( count( $rows ) >= $limit ) { break 2; } } } return $rows; } public static function paginated( $page = 1, $per_page = 10, $status_filter = null ) { $page = max( 1, (int) $page ); $all = self::recent( ( $page * $per_page ) + 1, $status_filter ); $has_next = count( $all ) > ( $page - 1 ) * $per_page + $per_page; $rows = array_slice( $all, ( $page - 1 ) * $per_page, $per_page ); return array( 'rows' => $rows, 'page' => $page, 'total_pages' => $page + ( $has_next ? 1 : 0 ), ); } public static function rollup_and_prune() { global $wpdb; $dir = self::log_dir(); if ( ! is_dir( $dir ) ) { return; } $table = Argus_DB::table( 'cache_stats_daily' ); $files = glob( trailingslashit( $dir ) . '*.log' ) ?: array(); foreach ( $files as $file ) { $basename = basename( $file, '.log' ); if ( ! preg_match( '/^\d{4}-\d{2}-\d{2}$/', $basename ) ) { continue; } $lines = file( $file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES ) ?: array(); $by_status = array(); foreach ( $lines as $line ) { $row = json_decode( $line, true ); if ( ! is_array( $row ) || empty( $row['s'] ) ) { continue; } $status = $row['s']; if ( ! isset( $by_status[ $status ] ) ) { $by_status[ $status ] = array( 'count' => 0, 'ms' => 0 ); } ++$by_status[ $status ]['count']; $by_status[ $status ]['ms'] += (int) ( $row['ms'] ?? 0 ); } foreach ( $by_status as $status => $agg ) { $wpdb->query( $wpdb->prepare( "INSERT INTO {$table} (stat_date, status, request_count, total_response_time_ms, total_bytes) VALUES (%s, %s, %d, %d, 0) ON DUPLICATE KEY UPDATE request_count = VALUES(request_count), total_response_time_ms = VALUES(total_response_time_ms)", // phpcs:ignore $basename, $status, $agg['count'], $agg['ms'] ) ); } } $cutoff = gmdate( 'Y-m-d', strtotime( '-' . self::RAW_RETENTION_DAYS . ' days' ) ); foreach ( $files as $file ) { $basename = basename( $file, '.log' ); if ( preg_match( '/^\d{4}-\d{2}-\d{2}$/', $basename ) && $basename < $cutoff ) { @unlink( $file ); // phpcs:ignore } } } public static function summary( $days = 7 ) { global $wpdb; $table = Argus_DB::table( 'cache_stats_daily' ); $since = gmdate( 'Y-m-d', strtotime( '-' . (int) $days . ' days' ) ); $rows = $wpdb->get_results( $wpdb->prepare( "SELECT status, SUM(request_count) AS cnt, SUM(total_response_time_ms) AS ms FROM {$table} WHERE stat_date >= %s GROUP BY status", // phpcs:ignore $since ) ); $out = array(); foreach ( $rows as $row ) { $cnt = (int) $row->cnt; $out[ $row->status ] = array( 'count' => $cnt, 'avg_ms' => $cnt > 0 ? (int) round( $row->ms / $cnt ) : null, ); } return $out; } public static function daily_series( $days = 14 ) { global $wpdb; $table = Argus_DB::table( 'cache_stats_daily' ); $since = gmdate( 'Y-m-d', strtotime( '-' . (int) $days . ' days' ) ); $rows = $wpdb->get_results( $wpdb->prepare( "SELECT stat_date, status, request_count FROM {$table} WHERE stat_date >= %s", $since ) // phpcs:ignore ); $by_date = array(); for ( $i = $days - 1; $i >= 0; $i-- ) { $d = gmdate( 'Y-m-d', strtotime( "-{$i} days" ) ); $by_date[ $d ] = array( 'date' => $d, 'hit' => 0, 'miss' => 0, 'bypass' => 0 ); } foreach ( $rows as $row ) { if ( ! isset( $by_date[ $row->stat_date ] ) ) { continue; } $key = strtolower( $row->status ); if ( isset( $by_date[ $row->stat_date ][ $key ] ) ) { $by_date[ $row->stat_date ][ $key ] += (int) $row->request_count; } } return array_values( $by_date ); } }