*/ private array $operations = []; /** * @param string $type Operation type: 'export', 'import', 'delete'. */ public function record( string $type, string $path, int $size, int $duration_ms ): void { $this->operations[] = [ 'type' => $type, 'path' => $path, 'size' => $size, 'duration_ms' => $duration_ms, 'timestamp' => microtime( true ), ]; } /** * Operations that exceeded a threshold. * * @return array */ public function get_slow_operations(): array { return array_values( array_filter( $this->operations, fn( $op ) => $op['duration_ms'] > self::SLOW_OP_THRESHOLD_MS || $op['size'] > self::LARGE_FILE_THRESHOLD ) ); } /** * @return array{ * total_operations: int, * total_bytes: int, * total_duration_ms: int, * by_type: array, * slow_count: int, * avg_duration_ms: int, * max_file_size: int, * } */ public function get_statistics(): array { $by_type = array_fill_keys( [ 'export', 'import', 'delete' ], 0 ); $total_bytes = 0; $total_duration = 0; $max_file = 0; foreach ( $this->operations as $op ) { $by_type[ $op['type'] ]++; $total_bytes += $op['size']; $total_duration += $op['duration_ms']; $max_file = max( $max_file, $op['size'] ); } $slow_count = count( $this->get_slow_operations() ); $count = count( $this->operations ); $avg = $count > 0 ? (int) ( $total_duration / $count ) : 0; return [ 'total_operations' => $count, 'total_bytes' => $total_bytes, 'total_duration_ms' => $total_duration, 'by_type' => $by_type, 'slow_count' => $slow_count, 'avg_duration_ms' => $avg, 'max_file_size' => $max_file, ]; } /** Human-readable report. */ public function get_report(): string { $stats = $this->get_statistics(); $slow = $this->get_slow_operations(); $slow_count = count( $slow ); $report = sprintf( "File Operation Audit Report\n" . "============================\n" . "Total operations: %d\n" . "Total data processed: %.2f MB\n" . "Total duration: %.2f seconds\n" . "Operations by type: export=%d, import=%d, delete=%d\n" . "Average duration per operation: %d ms\n" . "Largest file: %.2f MB\n" . "Slow operations (>%d ms or >100 MB): %d\n", $stats['total_operations'], $stats['total_bytes'] / 1_048_576, $stats['total_duration_ms'] / 1000, $stats['by_type']['export'], $stats['by_type']['import'], $stats['by_type']['delete'], $stats['avg_duration_ms'], $stats['max_file_size'] / 1_048_576, self::SLOW_OP_THRESHOLD_MS, $slow_count ); if ( ! empty( $slow ) ) { $report .= "\n\nSlow Operations:\n"; foreach ( array_slice( $slow, 0, 10 ) as $op ) { $report .= sprintf( " - %s: %s (%d ms, %.2f MB)\n", $op['type'], $op['path'], $op['duration_ms'], $op['size'] / 1_048_576 ); } } return $report; } public function clear(): void { $this->operations = []; } }