We use cookies for keeping user sessions alive and for site usage statistics.
Please accept cookies to continue browsing the site.

 

(You can decline cookies later navigating to page 'Privacy Policy'.)

Keep limited log file size in PHP/Laravel


We need to keep the log file size within decent limits. Last 10 MBytes should be enough for the general site health surveillance. The redundant leading part can be periodically deleted.

One option would be to use a temporary backup file as a ramp for swapping the retained content. A memory buffer would be necessary to transfer in chunks without engaging large areas of memory.

In order not to shrink upon every character added we implement a pulsing shrink algorithm, where the allowed maximum file size (the threshold) is larger than the size after the cyclic shrink operation.

Note that both files are locked for external access during the maintenance operation.

Put following function in a PHP file:

function shrinkFile($filePath, $bakFilePath, $maxFileSize, $shrinkedFileSize){
    $fileSize = filesize($filePath);

    if($fileSize > $maxFileSize){
        $handle = fopen($filePath, 'a+b');
        $bakHandle = fopen($bakFilePath, 'a+b');

        // position in main file requested new size before end of file
        if(fseek($handle, $fileSize - $shrinkedFileSize) === -1)
            return false;
    
        // clear the backup file
        if(!ftruncate($bakHandle, 0))
            return false;
        
        // copy the required new size portion to the temporary backup file
        while (!feof($handle)) {
            $buffer = fread($handle, 8192); 
            fwrite($bakHandle, $buffer);
        }

        // clear the main file
        if(!ftruncate($handle, 0))
            return false;
        
        // position at start of backup file
        if(!rewind($bakHandle))
            return false;
        
        // copy backup file to main file
        while (!feof($bakHandle)) {
            $buffer = fread($bakHandle, 8192); 
            fwrite($handle, $buffer);
        }

        // close streams
        fclose($handle);
        fclose($bakHandle);
    }
    
    // optionally delete the temporary backup file here
    //if(file_exists($bakFilePath))
        //unlink($bakFilePath);
    
    return true;
}

Now you can call that function periodically, e.g.:

  • in a cron job ones a day (probably the best option)
  • each time something is logged (would be too much)
  • with each http request (would be too much)
  • manually from time to time
  • etc.

Use following code with the right adaptation to your needs:

$filePath = storage_path() . '/logs/laravel.log'; 
$bakFilePath = storage_path() . '/logs/laravel.log.bak';
$maxFileSize = 11000000;
$shrinkedFileSize = 10000000;
 
$success = shrinkFile($filePath, $bakFilePath, $maxFileSize, $shrinkedFileSize);

For a cron job you would need home based paths:

$filePath = '/home/milevisc/storage/logs/laravel.log'; 
$bakFilePath = '/home/milevisc/storage/logs/laravel.log.bak';

Let's do it properly!


Back to List