├── src ├── Events │ ├── RotateHasFailed.php │ └── RotateWasSuccessful.php ├── Helpers │ └── Log.php ├── Commands │ ├── RotateCommand.php │ └── RotateFileCommand.php ├── Rotate.php └── RotateServiceProvider.php ├── LICENSE.md ├── .php-cs-fixer.dist.php ├── composer.json ├── config └── rotate.php └── README.md /src/Events/RotateHasFailed.php: -------------------------------------------------------------------------------- 1 | filename = $filename; 16 | 17 | $this->exception = $exception; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Events/RotateWasSuccessful.php: -------------------------------------------------------------------------------- 1 | filename = $filename; 14 | 15 | $this->filenameTarget = $filenameTarget; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Helpers/Log.php: -------------------------------------------------------------------------------- 1 | getUrl(); 23 | } 24 | } 25 | 26 | return $files; 27 | } 28 | 29 | public static function closeHandlers() 30 | { 31 | foreach (self::getHandlers() as $handler) { 32 | if ($handler instanceof StreamHandler && ! $handler instanceof RotatingFileHandler) { 33 | $handler->close(); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Cesargb 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/Commands/RotateCommand.php: -------------------------------------------------------------------------------- 1 | rotateLaravelLogs(); 18 | 19 | $this->rotareForeingFiles(); 20 | } 21 | 22 | protected function rotateLaravelLogs() 23 | { 24 | foreach (LogHelper::getLaravelLogFiles() as $file) { 25 | $this->line('Rotate file: '.$file); 26 | 27 | $this->rotateFile($file); 28 | } 29 | } 30 | 31 | protected function rotareForeingFiles() 32 | { 33 | foreach (config('rotate.foreign_files', []) as $file) { 34 | $this->line('Rotate file: '.$file); 35 | 36 | $this->rotateFile($file); 37 | } 38 | } 39 | 40 | protected function rotateFile(string $filename) 41 | { 42 | $rotation = new LaravelLogRotate(); 43 | 44 | $rotation->file($filename); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Commands/RotateFileCommand.php: -------------------------------------------------------------------------------- 1 | option('file') as $filename) { 21 | $this->line('Rotate file '.basename($filename).': '); 22 | 23 | $rotate = new Rotate(); 24 | 25 | $rotate->file($filename, [ 26 | 'files' => config('rotate.log_max_files', 366), 27 | 'compress' => config('rotate.log_compress_files', true), 28 | // 'then' => function () { 29 | // $this->line('ok'); 30 | // }, 31 | // 'catch' => function ($error) { 32 | // $this->error('failed: '.$error->getMessage().''); 33 | // }, 34 | ]); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Rotate.php: -------------------------------------------------------------------------------- 1 | file($filename); 16 | }); 17 | } 18 | 19 | public function file(string $filename, array $options = []): bool 20 | { 21 | $result = $this->buildRotateDefault($options)->rotate($filename); 22 | 23 | if ($result) { 24 | Log::closeHandlers(); 25 | } 26 | 27 | return $result; 28 | } 29 | 30 | private function buildRotateDefault(array $options = []): Rotation 31 | { 32 | return new Rotation(array_merge( 33 | [ 34 | 'files' => config('rotate.log_max_files', 366), 35 | 'compress' => config('rotate.log_compress_files', true), 36 | 'then' => function ($filenameRotated, $filename) { 37 | event(new RotateWasSuccessful($filename, $filenameRotated)); 38 | }, 39 | 'truncate' => config('rotate.truncate', true), 40 | 'catch' => function ($error) { 41 | event(new RotateHasFailed('', $error)); 42 | }, 43 | ], 44 | $options 45 | )); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | in([ 5 | __DIR__.'/src', 6 | __DIR__.'/tests', 7 | ]) 8 | ->name('*.php') 9 | ->notName('*.blade.php') 10 | ->ignoreDotFiles(true) 11 | ->ignoreVCS(true); 12 | 13 | return (new PhpCsFixer\Config()) 14 | ->setRules([ 15 | '@PSR12' => true, 16 | 'array_syntax' => ['syntax' => 'short'], 17 | 'ordered_imports' => ['sort_algorithm' => 'alpha'], 18 | 'no_unused_imports' => true, 19 | 'not_operator_with_successor_space' => true, 20 | 'trailing_comma_in_multiline' => true, 21 | 'phpdoc_scalar' => true, 22 | 'unary_operator_spaces' => true, 23 | 'binary_operator_spaces' => true, 24 | 'blank_line_before_statement' => [ 25 | 'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'], 26 | ], 27 | 'phpdoc_single_line_var_spacing' => true, 28 | 'phpdoc_var_without_name' => true, 29 | 'class_attributes_separation' => [ 30 | 'elements' => [ 31 | 'method' => 'one', 32 | ], 33 | ], 34 | 'method_argument_space' => [ 35 | 'on_multiline' => 'ensure_fully_multiline', 36 | 'keep_multiple_spaces_after_comma' => true, 37 | ], 38 | 'single_trait_insert_per_statement' => true, 39 | 'php_unit_method_casing' => ['case' => 'snake_case'], 40 | ]) 41 | ->setFinder($finder); -------------------------------------------------------------------------------- /src/RotateServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->runningInConsole()) { 20 | $this->publishes([ 21 | __DIR__.'/../config/rotate.php' => $this->app->configPath('rotate.php'), 22 | ], 'config'); 23 | 24 | $this->commands([ 25 | RotateCommand::class, 26 | RotateFileCommand::class, 27 | ]); 28 | 29 | $this->registerSchedule(); 30 | } 31 | } 32 | 33 | /** 34 | * Register the application services. 35 | * 36 | * @return void 37 | */ 38 | public function register() 39 | { 40 | $this->mergeConfigFrom(__DIR__.'/../config/rotate.php', 'rotate'); 41 | } 42 | 43 | private function registerSchedule() 44 | { 45 | if (! config('rotate.schedule.enable', true)) { 46 | return; 47 | } 48 | 49 | $this->callAfterResolving(Schedule::class, function (Schedule $schedule) { 50 | $cronOldVersion = config('rotate.logs_rotate_schedule', '0 0 * * *'); 51 | $cron = config('rotate.schedule.cron', $cronOldVersion); 52 | 53 | $schedule->command('rotate:logs')->cron($cron); 54 | }); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cesargb/laravel-logs-rotate", 3 | "description": "Rotate files log with compression", 4 | "keywords": [ 5 | "laravel", 6 | "logs", 7 | "rotate", 8 | "compression" 9 | ], 10 | "homepage": "https://github.com/cesargb/laravel-logs-rotate", 11 | "authors": [ 12 | { 13 | "name": "Cesar Garcia", 14 | "email": "cesargb@gmail.com", 15 | "homepage": "https://github.com/cesargb", 16 | "role": "Developer" 17 | } 18 | ], 19 | "license": "MIT", 20 | "require": { 21 | "php": "^8.0", 22 | "illuminate/config": "^10.0|^11.0|^12.0", 23 | "illuminate/console": "^10.0|^11.0|^12.0", 24 | "illuminate/log": "^10.0|^11.0|^12.0", 25 | "illuminate/support": "^10.0|^11.0|^12.0", 26 | "monolog/monolog": "^2.0|^3.0|^11.0", 27 | "cesargb/php-log-rotation": "^2.7" 28 | }, 29 | "require-dev": { 30 | "phpunit/phpunit": "^10.5|^11.5.3", 31 | "friendsofphp/php-cs-fixer": "^3.13", 32 | "orchestra/testbench": "^8.0|^9.0|^10.0", 33 | "larastan/larastan": "^2.0|^3.0" 34 | }, 35 | "autoload": { 36 | "psr-4": { 37 | "Cesargb\\LaravelLog\\": "src" 38 | } 39 | }, 40 | "autoload-dev": { 41 | "psr-4": { 42 | "Cesargb\\LaravelLog\\Test\\": "tests" 43 | } 44 | }, 45 | "scripts": { 46 | "test": "vendor/bin/phpunit --colors=always" 47 | }, 48 | "extra": { 49 | "laravel": { 50 | "providers": [ 51 | "Cesargb\\LaravelLog\\RotateServiceProvider" 52 | ] 53 | } 54 | }, 55 | "minimum-stability": "dev", 56 | "prefer-stable": true 57 | } 58 | -------------------------------------------------------------------------------- /config/rotate.php: -------------------------------------------------------------------------------- 1 | true, 13 | 14 | /* 15 | |-------------------------------------------------------------------------- 16 | | Schedule Rotate 17 | |-------------------------------------------------------------------------- 18 | | 19 | | Determine when must be run the cron. 20 | | You can disable the schedule change the option enable at false. 21 | | You can change the frequency with option cron. 22 | | 23 | */ 24 | 'schedule' => [ 25 | 'enable' => true, 26 | 'cron' => '0 0 * * *', 27 | ], 28 | 29 | /* 30 | |-------------------------------------------------------------------------- 31 | | Max Files Rotated 32 | |-------------------------------------------------------------------------- 33 | | 34 | | This value determine the max number of files rotated in the archive folder. 35 | | 36 | */ 37 | 'log_max_files' => env('LOG_MAX_FILES', 5), 38 | 39 | /* 40 | |-------------------------------------------------------------------------- 41 | | Truncate Log file 42 | |-------------------------------------------------------------------------- 43 | | 44 | | This option defines if the log file must be truncated after rotated. 45 | | If you prefer not truncate file, set this value at false. 46 | */ 47 | 'truncate' => env('LOG_TRUNCATE', true), 48 | 49 | /* 50 | |-------------------------------------------------------------------------- 51 | | Other files to rotated 52 | |-------------------------------------------------------------------------- 53 | | 54 | | Array the other foreing files 55 | | 56 | | Example: 57 | | 'foreign_files' => [ 58 | storage_path('/logs/worker.log') 59 | | ] 60 | | 61 | */ 62 | 'foreign_files' => [], 63 | ]; 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rotate Laravel logs files and compress 2 | 3 | ![tests](https://github.com/cesargb/laravel-logs-rotate/workflows/tests/badge.svg) 4 | [![style](https://github.com/cesargb/laravel-logs-rotate/actions/workflows/style-fix.yml/badge.svg)](https://github.com/cesargb/laravel-logs-rotate/actions/workflows/style-fix.yml) 5 | [![phpstan](https://github.com/cesargb/laravel-logs-rotate/actions/workflows/phpstan.yml/badge.svg)](https://github.com/cesargb/laravel-logs-rotate/actions/workflows/phpstan.yml) 6 | [![Latest Stable Version](https://img.shields.io/packagist/v/cesargb/laravel-logs-rotate.svg)](https://packagist.org/packages/cesargb/laravel-logs-rotate) 7 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/cesargb/laravel-logs-rotate/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/cesargb/laravel-logs-rotate/?branch=master) 8 | 9 | This package allows you to rotate the Laravel record file with compression. This method is useful if you use logger channel `single` (StreamHandler) 10 | 11 | ## Installation 12 | 13 | This package can be used in Laravel 5.5 or higher. 14 | 15 | You can install the package via composer: 16 | 17 | ```bash 18 | composer require cesargb/laravel-logs-rotate 19 | ``` 20 | 21 | ## Usage 22 | 23 | At this moment, every day at 00:00 your application executes a schedule to rotate the Laravel record files. 24 | 25 | ## Configuration 26 | 27 | If you need to change the frequency or another function, you can modify the config file. 28 | 29 | You can publish config file with: 30 | 31 | ```bash 32 | php artisan vendor:publish --provider="Cesargb\LaravelLog\RotateServiceProvider" --tag=config 33 | ``` 34 | 35 | This is the contents of the published config/rotate.php config file: 36 | 37 | ```php 38 | true, 50 | 51 | /* 52 | |-------------------------------------------------------------------------- 53 | | Schedule Rotate 54 | |-------------------------------------------------------------------------- 55 | | 56 | | Determine when must be run the cron. 57 | | You can disable the schedule change the option enable at false. 58 | | You can change the frequency with option cron. 59 | | 60 | */ 61 | 'schedule' => [ 62 | 'enable' => true, 63 | 'cron' => '0 0 * * *', 64 | ], 65 | 66 | /* 67 | |-------------------------------------------------------------------------- 68 | | Max Files Rotated 69 | |-------------------------------------------------------------------------- 70 | | 71 | | This value determine the max number of files rotated in the archive folder. 72 | | 73 | */ 74 | 'log_max_files' => env('LOG_MAX_FILES', 5), 75 | 76 | /* 77 | |-------------------------------------------------------------------------- 78 | | Truncate Log file 79 | |-------------------------------------------------------------------------- 80 | | 81 | | This option defines if the log file must be truncated after rotated. 82 | | If you prefer not truncate file, set this value at false. 83 | */ 84 | 'truncate' => env('LOG_TRUNCATE', true), 85 | 86 | /* 87 | |-------------------------------------------------------------------------- 88 | | Other files to rotated 89 | |-------------------------------------------------------------------------- 90 | | 91 | | Array the other foreing files 92 | | 93 | | Example: 94 | | 'foreign_files' => [ 95 | storage_path('/logs/worker.log') 96 | | ] 97 | | 98 | */ 99 | 'foreign_files' => [] 100 | ]; 101 | ``` 102 | 103 | ## Command 104 | 105 | You have a command to rotate other files, `rotate:files` 106 | 107 | ```bash 108 | php artisan rotate:files --help 109 | Description: 110 | Rotate files 111 | 112 | Usage: 113 | rotate:files [options] 114 | 115 | Options: 116 | -f, --file[=FILE] Files to rotate (multiple values allowed) 117 | -c, --compress[=COMPRESS] Compress the file rotated [default: "true"] 118 | -m, --max-files[=MAX-FILES] Max files rotated [default: "5"] 119 | -d, --dir[=DIR] Dir where archive the file rotated 120 | ``` 121 | 122 | ## Events 123 | 124 | Every time a file is rotated one of these events occurs: 125 | 126 | ### RotateWasSuccessful 127 | 128 | `Cesargb\LaravelLog\Events\RotateWasSuccessful` 129 | 130 | This event will be fired when rotated was successful. 131 | 132 | It has two public properties: 133 | 134 | * filename: the full path of file to rotate 135 | * filenameTarget: the full path of file rotated 136 | 137 | ### RotateHasFailed 138 | 139 | `Cesargb\LaravelLog\Events\RotativeHandler` 140 | 141 | This event will be fired when an error occurs while rotated 142 | 143 | It has two public properties: 144 | 145 | * filename: the full path of file to rotate 146 | * exception: an object that extends PHP's Exception class. 147 | 148 | ## About 149 | 150 | You can only rotate the logs file was generate with logger channel StreamHandler. 151 | 152 | ## Test 153 | 154 | Run test with: 155 | 156 | ```bash 157 | composer test 158 | ``` 159 | 160 | ## Upgrading 161 | 162 | Please see [UPGRADING](UPGRADING.md) for details. 163 | 164 | ## Contributing 165 | 166 | Any contributions are welcome. 167 | 168 | ## License 169 | 170 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 171 | --------------------------------------------------------------------------------