├── LICENSE.md ├── README.md ├── composer.json ├── config └── log-viewer.php ├── helpers.php ├── src ├── Commands │ ├── CheckCommand.php │ ├── ClearCommand.php │ ├── Command.php │ ├── PublishCommand.php │ └── StatsCommand.php ├── Contracts │ ├── LogViewer.php │ ├── Patternable.php │ ├── Table.php │ └── Utilities │ │ ├── Factory.php │ │ ├── Filesystem.php │ │ ├── LogChecker.php │ │ ├── LogLevels.php │ │ ├── LogMenu.php │ │ └── LogStyler.php ├── Entities │ ├── Log.php │ ├── LogCollection.php │ ├── LogEntry.php │ └── LogEntryCollection.php ├── Exceptions │ ├── FilesystemException.php │ ├── LogNotFoundException.php │ └── LogViewerException.php ├── Helpers │ └── LogParser.php ├── Http │ ├── Controllers │ │ └── LogViewerController.php │ └── Routes │ │ └── LogViewerRoute.php ├── LogViewer.php ├── LogViewerServiceProvider.php ├── Providers │ ├── DeferredServicesProvider.php │ └── RouteServiceProvider.php ├── Tables │ ├── AbstractTable.php │ └── StatsTable.php └── Utilities │ ├── Factory.php │ ├── Filesystem.php │ ├── LogChecker.php │ ├── LogLevels.php │ ├── LogMenu.php │ └── LogStyler.php ├── translations ├── ar.json ├── bg.json ├── bn.json ├── de.json ├── es.json ├── et.json ├── fa.json ├── fr.json ├── he.json ├── hu.json ├── hy.json ├── id.json ├── it.json ├── ja.json ├── ko.json ├── ms.json ├── nl.json ├── pl.json ├── pt-BR.json ├── ro.json ├── ru.json ├── si.json ├── sv.json ├── th.json ├── tr.json ├── uk.json ├── uz.json ├── zh-TW.json └── zh.json └── views ├── bootstrap-3 ├── _master.blade.php ├── dashboard.blade.php ├── logs.blade.php └── show.blade.php ├── bootstrap-4 ├── _master.blade.php ├── dashboard.blade.php ├── logs.blade.php └── show.blade.php └── bootstrap-5 ├── _master.blade.php ├── dashboard.blade.php ├── logs.blade.php └── show.blade.php /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) ARCANEDEV 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LogViewer [![Packagist License][badge_license]](LICENSE.md) [![For Laravel][badge_laravel]][link-github-repo] 2 | 3 | [![Github Workflow Status][badge_build]][link-github-status] 4 | [![Coverage Status][badge_coverage]][link-scrutinizer] 5 | [![Scrutinizer Code Quality][badge_quality]][link-scrutinizer] 6 | [![SensioLabs Insight][badge_insight]][link-insight] 7 | [![Github Issues][badge_issues]][link-github-issues] 8 | 9 | [![Packagist][badge_package]][link-packagist] 10 | [![Packagist Release][badge_release]][link-packagist] 11 | [![Packagist Downloads][badge_downloads]][link-packagist] 12 | 13 | *By [ARCANEDEV©](http://www.arcanedev.net/)* 14 | 15 | This package allows you to manage and keep track of each one of your log files. 16 | 17 | > **NOTE: You can also use LogViewer as an API.** 18 | 19 | Official documentation for LogViewer can be found at the [_docs folder](_docs/1.Installation-and-Setup.md). 20 | 21 | Feel free to check out the [releases](https://github.com/ARCANEDEV/LogViewer/releases), [license](LICENSE.md), and [contribution guidelines](CONTRIBUTING.md). 22 | 23 | ## Features 24 | 25 | - A great Log viewer API. 26 | - Laravel `5.x` to `11.x` are supported. 27 | - Ready to use (Views, Routes, controllers … Out of the box) [Note: No need to publish assets] 28 | - View, paginate, filter, download and delete logs. 29 | - Load a custom logs storage path. 30 | - Localized log levels. 31 | - Logs menu/tree generator. 32 | - Grouped logs by dates and levels. 33 | - Customized log levels icons (font awesome by default). 34 | - Works great with big logs !! 35 | - Well documented package (IDE Friendly). 36 | - Well tested (100% code coverage with maximum code quality). 37 | 38 | ## Table of contents 39 | 40 | 1. [Installation and Setup](_docs/1.Installation-and-Setup.md) 41 | 2. [Configuration](_docs/2.Configuration.md) 42 | 3. [Usage](_docs/3.Usage.md) 43 | 44 | ### Supported localizations 45 | 46 | > Dear artisans, i'm counting on you to help me out to add more translations ( ^_^)b 47 | 48 | | Local | Language | 49 | |---------|-----------------------| 50 | | `ar` | Arabic | 51 | | `bg` | Bulgarian | 52 | | `bn` | Bengali | 53 | | `de` | German | 54 | | `en` | English | 55 | | `es` | Spanish | 56 | | `et` | Estonian | 57 | | `fa` | Farsi | 58 | | `fr` | French | 59 | | `he` | Hebrew | 60 | | `hu` | Hungarian | 61 | | `hy` | Armenian | 62 | | `id` | Indonesian | 63 | | `it` | Italian | 64 | | `ja` | Japanese | 65 | | `ko` | Korean | 66 | | `ms` | Malay | 67 | | `nl` | Dutch | 68 | | `pl` | Polish | 69 | | `pt-BR` | Brazilian Portuguese | 70 | | `ro` | Romanian | 71 | | `ru` | Russian | 72 | | `si` | Sinhalese | 73 | | `sv` | Swedish | 74 | | `th` | Thai | 75 | | `tr` | Turkish | 76 | | `uk` | Ukrainian | 77 | | `uz` | Uzbek | 78 | | `zh` | Chinese (Simplified) | 79 | | `zh-TW` | Chinese (Traditional) | 80 | 81 | ## Contribution 82 | 83 | Any ideas are welcome. Feel free to submit any issues or pull requests, please check the [contribution guidelines](CONTRIBUTING.md). 84 | 85 | ## Security 86 | 87 | If you discover any security related issues, please email arcanedev.maroc@gmail.com instead of using the issue tracker. 88 | 89 | ## Credits 90 | 91 | - [ARCANEDEV][link-author] 92 | - [All Contributors][link-contributors] 93 | 94 | ## PREVIEW 95 | 96 | ![Dashboard](https://raw.githubusercontent.com/ARCANEDEV/LogViewer/master/_screenshots/1-dashboard.jpg) 97 | ![Logs list](https://raw.githubusercontent.com/ARCANEDEV/LogViewer/master/_screenshots/2-logs-list.jpg) 98 | ![Single log](https://raw.githubusercontent.com/ARCANEDEV/LogViewer/master/_screenshots/3-single-log.jpg) 99 | 100 | [badge_laravel]: https://img.shields.io/badge/Laravel-5.x%20to%2011.x-orange.svg?style=flat-square 101 | [badge_license]: https://img.shields.io/packagist/l/arcanedev/log-viewer.svg?style=flat-square 102 | [badge_build]: https://img.shields.io/github/workflow/status/ARCANEDEV/LogViewer/run-tests?style=flat-square 103 | [badge_coverage]: https://img.shields.io/scrutinizer/coverage/g/ARCANEDEV/LogViewer.svg?style=flat-square 104 | [badge_quality]: https://img.shields.io/scrutinizer/g/ARCANEDEV/LogViewer.svg?style=flat-square 105 | [badge_insight]: https://img.shields.io/sensiolabs/i/d6b4587a-e00d-4dac-98db-f979731fdc4d.svg?style=flat-square 106 | [badge_issues]: https://img.shields.io/github/issues/ARCANEDEV/LogViewer.svg?style=flat-square 107 | [badge_package]: https://img.shields.io/badge/package-arcanedev/log--viewer-blue.svg?style=flat-square 108 | [badge_release]: https://img.shields.io/packagist/v/arcanedev/log-viewer.svg?style=flat-square 109 | [badge_downloads]: https://img.shields.io/packagist/dt/arcanedev/log-viewer.svg?style=flat-square 110 | 111 | [link-author]: https://github.com/arcanedev-maroc 112 | [link-github-status]: https://github.com/ARCANEDEV/LogViewer/actions 113 | [link-github-repo]: https://github.com/ARCANEDEV/LogViewer 114 | [link-github-issues]: https://github.com/ARCANEDEV/LogViewer/issues 115 | [link-contributors]: https://github.com/ARCANEDEV/LogViewer/graphs/contributors 116 | [link-packagist]: https://packagist.org/packages/arcanedev/log-viewer 117 | [link-scrutinizer]: https://scrutinizer-ci.com/g/ARCANEDEV/LogViewer/?branch=master 118 | [link-insight]: https://insight.sensiolabs.com/projects/d6b4587a-e00d-4dac-98db-f979731fdc4d 119 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "arcanedev/log-viewer", 3 | "description": "Provides a Log Viewer for Laravel", 4 | "keywords": ["arcanedev", "arcanesoft", "laravel", "log", "log viewer", "log-viewer", "logviewer"], 5 | "homepage": "https://github.com/ARCANEDEV/LogViewer", 6 | "authors": [ 7 | { 8 | "name": "ARCANEDEV", 9 | "email": "arcanedev.maroc@gmail.com", 10 | "homepage": "https://github.com/arcanedev-maroc", 11 | "role": "Developer" 12 | } 13 | ], 14 | "type": "library", 15 | "license": "MIT", 16 | "require": { 17 | "php": "^8.2", 18 | "ext-json": "*", 19 | "arcanedev/support": "^11.0", 20 | "psr/log": "^1.0|^2.0|^3.0" 21 | }, 22 | "require-dev": { 23 | "laravel/framework": "^11.0", 24 | "mockery/mockery": "^1.6", 25 | "orchestra/testbench-core": "^9.0", 26 | "phpunit/phpunit": "^10.5" 27 | }, 28 | "autoload": { 29 | "psr-4": { 30 | "Arcanedev\\LogViewer\\": "src/" 31 | }, 32 | "files": ["helpers.php"] 33 | }, 34 | "autoload-dev": { 35 | "psr-4": { 36 | "Arcanedev\\LogViewer\\Tests\\": "tests/" 37 | } 38 | }, 39 | "scripts": { 40 | "test": "phpunit --colors=always", 41 | "test:dox": "phpunit --testdox --colors=always", 42 | "test:cov": "phpunit --coverage-html build/coverage" 43 | }, 44 | "extra": { 45 | "branch-alias": { 46 | "dev-develop": "11.x-dev" 47 | }, 48 | "laravel": { 49 | "providers": [ 50 | "Arcanedev\\LogViewer\\LogViewerServiceProvider", 51 | "Arcanedev\\LogViewer\\Providers\\DeferredServicesProvider" 52 | ] 53 | } 54 | }, 55 | "config": { 56 | "sort-packages": true 57 | }, 58 | "minimum-stability": "dev", 59 | "prefer-stable": true 60 | } 61 | -------------------------------------------------------------------------------- /config/log-viewer.php: -------------------------------------------------------------------------------- 1 | storage_path('logs'), 13 | 14 | /* ----------------------------------------------------------------- 15 | | Log files pattern 16 | | ----------------------------------------------------------------- 17 | */ 18 | 19 | 'pattern' => [ 20 | 'prefix' => Filesystem::PATTERN_PREFIX, // 'laravel-' 21 | 'date' => Filesystem::PATTERN_DATE, // '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]' 22 | 'extension' => Filesystem::PATTERN_EXTENSION, // '.log' 23 | ], 24 | 25 | /* ----------------------------------------------------------------- 26 | | Locale 27 | | ----------------------------------------------------------------- 28 | | Supported locales : 29 | | 'auto', 'ar', 'bg', 'de', 'en', 'es', 'et', 'fa', 'fr', 'hu', 'hy', 'id', 'it', 'ja', 'ko', 'nl', 30 | | 'pl', 'pt-BR', 'ro', 'ru', 'sv', 'th', 'tr', 'zh-TW', 'zh' 31 | */ 32 | 33 | 'locale' => 'auto', 34 | 35 | /* ----------------------------------------------------------------- 36 | | Theme 37 | | ----------------------------------------------------------------- 38 | | Supported themes : 39 | | 'bootstrap-5' 40 | | 'bootstrap-4' 41 | | 'bootstrap-3' 42 | | 43 | | You can make your own theme by adding a folder to the views directory and specifying it here. 44 | */ 45 | 46 | 'theme' => 'bootstrap-5', 47 | 48 | /* ----------------------------------------------------------------- 49 | | Route settings 50 | | ----------------------------------------------------------------- 51 | */ 52 | 53 | 'route' => [ 54 | 'enabled' => true, 55 | 56 | 'attributes' => [ 57 | 'prefix' => 'log-viewer', 58 | 59 | 'middleware' => env('ARCANEDEV_LOGVIEWER_MIDDLEWARE') ? explode(',', env('ARCANEDEV_LOGVIEWER_MIDDLEWARE')) : null, 60 | ], 61 | 62 | 'show' => 'log-viewer::logs.show', 63 | ], 64 | 65 | /* ----------------------------------------------------------------- 66 | | Log entries per page 67 | | ----------------------------------------------------------------- 68 | | This defines how many logs & entries are displayed per page. 69 | */ 70 | 71 | 'per-page' => 30, 72 | 73 | /* ----------------------------------------------------------------- 74 | | Download settings 75 | | ----------------------------------------------------------------- 76 | */ 77 | 78 | 'download' => [ 79 | 'prefix' => 'laravel-', 80 | 81 | 'extension' => 'log', 82 | ], 83 | 84 | /* ----------------------------------------------------------------- 85 | | Menu settings 86 | | ----------------------------------------------------------------- 87 | */ 88 | 89 | 'menu' => [ 90 | 'filter-route' => 'log-viewer::logs.filter', 91 | 92 | 'icons-enabled' => true, 93 | ], 94 | 95 | /* ----------------------------------------------------------------- 96 | | Icons 97 | | ----------------------------------------------------------------- 98 | */ 99 | 100 | 'icons' => [ 101 | /** 102 | * Font awesome >= 4.3 103 | * http://fontawesome.io/icons/ 104 | */ 105 | 'all' => 'fa fa-fw fa-list', // http://fontawesome.io/icon/list/ 106 | 'emergency' => 'fa fa-fw fa-bug', // http://fontawesome.io/icon/bug/ 107 | 'alert' => 'fa fa-fw fa-bullhorn', // http://fontawesome.io/icon/bullhorn/ 108 | 'critical' => 'fa fa-fw fa-heartbeat', // http://fontawesome.io/icon/heartbeat/ 109 | 'error' => 'fa fa-fw fa-times-circle', // http://fontawesome.io/icon/times-circle/ 110 | 'warning' => 'fa fa-fw fa-exclamation-triangle', // http://fontawesome.io/icon/exclamation-triangle/ 111 | 'notice' => 'fa fa-fw fa-exclamation-circle', // http://fontawesome.io/icon/exclamation-circle/ 112 | 'info' => 'fa fa-fw fa-info-circle', // http://fontawesome.io/icon/info-circle/ 113 | 'debug' => 'fa fa-fw fa-life-ring', // http://fontawesome.io/icon/life-ring/ 114 | ], 115 | 116 | /* ----------------------------------------------------------------- 117 | | Colors 118 | | ----------------------------------------------------------------- 119 | */ 120 | 121 | 'colors' => [ 122 | 'levels' => [ 123 | 'empty' => '#D1D1D1', 124 | 'all' => '#8A8A8A', 125 | 'emergency' => '#B71C1C', 126 | 'alert' => '#D32F2F', 127 | 'critical' => '#F44336', 128 | 'error' => '#FF5722', 129 | 'warning' => '#FF9100', 130 | 'notice' => '#4CAF50', 131 | 'info' => '#1976D2', 132 | 'debug' => '#90CAF9', 133 | ], 134 | ], 135 | 136 | /* ----------------------------------------------------------------- 137 | | Strings to highlight in stack trace 138 | | ----------------------------------------------------------------- 139 | */ 140 | 141 | 'highlight' => [ 142 | '^#\d+', 143 | '^Stack trace:', 144 | ], 145 | 146 | ]; 147 | -------------------------------------------------------------------------------- /helpers.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class CheckCommand extends Command 15 | { 16 | /* ----------------------------------------------------------------- 17 | | Properties 18 | | ----------------------------------------------------------------- 19 | */ 20 | 21 | /** 22 | * The console command name. 23 | * 24 | * @var string 25 | */ 26 | protected $name = 'log-viewer:check'; 27 | 28 | /** 29 | * The console command description. 30 | * 31 | * @var string 32 | */ 33 | protected $description = 'Check all LogViewer requirements.'; 34 | 35 | /** 36 | * The name and signature of the console command. 37 | * 38 | * @var string 39 | */ 40 | protected $signature = 'log-viewer:check'; 41 | 42 | /* ----------------------------------------------------------------- 43 | | Getter & Setters 44 | | ----------------------------------------------------------------- 45 | */ 46 | 47 | /** 48 | * Get the Log Checker instance. 49 | * 50 | * @return \Arcanedev\LogViewer\Contracts\Utilities\LogChecker 51 | */ 52 | protected function getChecker() 53 | { 54 | return $this->laravel[LogCheckerContract::class]; 55 | } 56 | 57 | /* ----------------------------------------------------------------- 58 | | Main Methods 59 | | ----------------------------------------------------------------- 60 | */ 61 | 62 | /** 63 | * Execute the console command. 64 | */ 65 | public function handle(): int 66 | { 67 | $this->displayLogViewer(); 68 | $this->displayRequirements(); 69 | $this->displayMessages(); 70 | 71 | return static::SUCCESS; 72 | } 73 | 74 | /* ----------------------------------------------------------------- 75 | | Other Methods 76 | | ----------------------------------------------------------------- 77 | */ 78 | 79 | /** 80 | * Display LogViewer requirements. 81 | */ 82 | private function displayRequirements() 83 | { 84 | $requirements = $this->getChecker()->requirements(); 85 | 86 | $this->frame('Application requirements'); 87 | 88 | $this->table([ 89 | 'Status', 'Message' 90 | ], [ 91 | [$requirements['status'], $requirements['message']] 92 | ]); 93 | } 94 | 95 | /** 96 | * Display LogViewer messages. 97 | */ 98 | private function displayMessages() 99 | { 100 | $messages = $this->getChecker()->messages(); 101 | 102 | $rows = []; 103 | foreach ($messages['files'] as $file => $message) { 104 | $rows[] = [$file, $message]; 105 | } 106 | 107 | if ( ! empty($rows)) { 108 | $this->frame('LogViewer messages'); 109 | $this->table(['File', 'Message'], $rows); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/Commands/ClearCommand.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class ClearCommand extends Command 13 | { 14 | /* ----------------------------------------------------------------- 15 | | Properties 16 | | ----------------------------------------------------------------- 17 | */ 18 | 19 | /** 20 | * The name and signature of the console command. 21 | * 22 | * @var string 23 | */ 24 | protected $signature = 'log-viewer:clear'; 25 | 26 | /** 27 | * The console command description. 28 | * 29 | * @var string 30 | */ 31 | protected $description = 'Clear all generated log files'; 32 | 33 | /* ----------------------------------------------------------------- 34 | | Main Methods 35 | | ----------------------------------------------------------------- 36 | */ 37 | 38 | /** 39 | * Execute the console command. 40 | */ 41 | public function handle(): int 42 | { 43 | if ($this->confirm('This will delete all the log files, Do you wish to continue?')) { 44 | $this->logViewer->clear(); 45 | $this->info('Successfully cleared the logs!'); 46 | } 47 | 48 | return static::SUCCESS; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Commands/Command.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | abstract class Command extends BaseCommand 16 | { 17 | /* ----------------------------------------------------------------- 18 | | Properties 19 | | ----------------------------------------------------------------- 20 | */ 21 | 22 | /** @var \Arcanedev\LogViewer\Contracts\LogViewer */ 23 | protected $logViewer; 24 | 25 | /* ----------------------------------------------------------------- 26 | | Constructor 27 | | ----------------------------------------------------------------- 28 | */ 29 | 30 | /** 31 | * Create the command instance. 32 | * 33 | * @param \Arcanedev\LogViewer\Contracts\LogViewer $logViewer 34 | */ 35 | public function __construct(LogViewerContract $logViewer) 36 | { 37 | parent::__construct(); 38 | 39 | $this->logViewer = $logViewer; 40 | } 41 | 42 | /* ----------------------------------------------------------------- 43 | | Other Methods 44 | | ----------------------------------------------------------------- 45 | */ 46 | 47 | /** 48 | * Display LogViewer Logo and Copyrights. 49 | */ 50 | protected function displayLogViewer() 51 | { 52 | // LOGO 53 | $this->comment(' __ _ '); 54 | $this->comment(' / / ___ __ _/\ /(_) _____ _____ _ __ '); 55 | $this->comment(' / / / _ \ / _` \ \ / / |/ _ \ \ /\ / / _ \ \'__|'); 56 | $this->comment('/ /__| (_) | (_| |\ V /| | __/\ V V / __/ | '); 57 | $this->comment('\____/\___/ \__, | \_/ |_|\___| \_/\_/ \___|_| '); 58 | $this->comment(' |___/ '); 59 | $this->line(''); 60 | 61 | // Copyright 62 | $this->comment('Version '.$this->logViewer->version().' - Created by ARCANEDEV'.chr(169)); 63 | $this->line(''); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Commands/PublishCommand.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class PublishCommand extends Command 16 | { 17 | /* ----------------------------------------------------------------- 18 | | Properties 19 | | ----------------------------------------------------------------- 20 | */ 21 | 22 | /** 23 | * The console command name. 24 | * 25 | * @var string 26 | */ 27 | protected $name = 'log-viewer:publish'; 28 | 29 | /** 30 | * The console command description. 31 | * 32 | * @var string 33 | */ 34 | protected $description = 'Publish all LogViewer resources and config files'; 35 | 36 | /** 37 | * The name and signature of the console command. 38 | * 39 | * @var string 40 | */ 41 | protected $signature = 'log-viewer:publish 42 | {--tag= : One or many tags that have assets you want to publish.} 43 | {--force : Overwrite any existing files.}'; 44 | 45 | /* ----------------------------------------------------------------- 46 | | Main Methods 47 | | ----------------------------------------------------------------- 48 | */ 49 | 50 | /** 51 | * Execute the console command. 52 | */ 53 | public function handle(): int 54 | { 55 | $args = [ 56 | '--provider' => LogViewerServiceProvider::class, 57 | ]; 58 | 59 | if ((bool) $this->option('force')) { 60 | $args['--force'] = true; 61 | } 62 | 63 | $args['--tag'] = [$this->option('tag')]; 64 | 65 | $this->displayLogViewer(); 66 | $this->call('vendor:publish', $args); 67 | 68 | return static::SUCCESS; 69 | } 70 | 71 | /** 72 | * Get the console command options. 73 | * 74 | * @return array 75 | * 76 | * @codeCoverageIgnore 77 | */ 78 | protected function getOptions() 79 | { 80 | return [ 81 | ['tag', 't', InputOption::VALUE_OPTIONAL, 'One or many tags that have assets you want to publish.', ''], 82 | ['force', 'f', InputOption::VALUE_OPTIONAL, 'Overwrite any existing files.', false], 83 | ]; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/Commands/StatsCommand.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class StatsCommand extends Command 15 | { 16 | /* ----------------------------------------------------------------- 17 | | Properties 18 | | ----------------------------------------------------------------- 19 | */ 20 | 21 | /** 22 | * The console command name. 23 | * 24 | * @var string 25 | */ 26 | protected $name = 'log-viewer:stats'; 27 | 28 | /** 29 | * The console command description. 30 | * 31 | * @var string 32 | */ 33 | protected $description = 'Display stats of all logs.'; 34 | 35 | /** 36 | * The name and signature of the console command. 37 | * 38 | * @var string 39 | */ 40 | protected $signature = 'log-viewer:stats'; 41 | 42 | /* ----------------------------------------------------------------- 43 | | Main Methods 44 | | ----------------------------------------------------------------- 45 | */ 46 | 47 | /** 48 | * Execute the console command. 49 | */ 50 | public function handle() 51 | { 52 | // Load Data 53 | $stats = $this->logViewer->statsTable('en'); 54 | 55 | $rows = $stats->rows(); 56 | $rows[] = $this->tableSeparator(); 57 | $rows[] = $this->prepareFooter($stats); 58 | 59 | // Display Data 60 | $this->displayLogViewer(); 61 | $this->table($stats->header(), $rows); 62 | 63 | return static::SUCCESS; 64 | } 65 | 66 | /* ----------------------------------------------------------------- 67 | | Other Methods 68 | | ----------------------------------------------------------------- 69 | */ 70 | 71 | /** 72 | * Prepare footer. 73 | * 74 | * @param \Arcanedev\LogViewer\Tables\StatsTable $stats 75 | * 76 | * @return array 77 | */ 78 | private function prepareFooter(StatsTable $stats) 79 | { 80 | $files = [ 81 | 'count' => count($stats->rows()).' log file(s)' 82 | ]; 83 | 84 | return $files + $stats->footer(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Contracts/LogViewer.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | interface LogViewer extends Patternable 13 | { 14 | /* ----------------------------------------------------------------- 15 | | Getters & Methods 16 | | ----------------------------------------------------------------- 17 | */ 18 | 19 | /** 20 | * Get the log levels. 21 | * 22 | * @param bool|false $flip 23 | * 24 | * @return array 25 | */ 26 | public function levels($flip = false); 27 | 28 | /** 29 | * Get the translated log levels. 30 | * 31 | * @param string|null $locale 32 | * 33 | * @return array 34 | */ 35 | public function levelsNames($locale = null); 36 | 37 | /** 38 | * Set the log storage path. 39 | * 40 | * @param string $path 41 | * 42 | * @return self 43 | */ 44 | public function setPath($path); 45 | 46 | /* ----------------------------------------------------------------- 47 | | Main Methods 48 | | ----------------------------------------------------------------- 49 | */ 50 | 51 | /** 52 | * Get all logs. 53 | * 54 | * @return \Arcanedev\LogViewer\Entities\LogCollection|\Arcanedev\LogViewer\Entities\Log[] 55 | */ 56 | public function all(); 57 | 58 | /** 59 | * Paginate all logs. 60 | * 61 | * @param int $perPage 62 | * 63 | * @return \Illuminate\Pagination\LengthAwarePaginator 64 | */ 65 | public function paginate($perPage = 30); 66 | 67 | /** 68 | * Get a log. 69 | * 70 | * @param string $date 71 | * 72 | * @return \Arcanedev\LogViewer\Entities\Log 73 | */ 74 | public function get($date); 75 | 76 | /** 77 | * Get the log entries. 78 | * 79 | * @param string $date 80 | * @param string $level 81 | * 82 | * @return \Arcanedev\LogViewer\Entities\LogEntryCollection 83 | */ 84 | public function entries($date, $level = 'all'); 85 | 86 | /** 87 | * Download a log file. 88 | * 89 | * @param string $date 90 | * @param string|null $filename 91 | * @param array $headers 92 | * 93 | * @return \Symfony\Component\HttpFoundation\BinaryFileResponse 94 | */ 95 | public function download($date, $filename = null, $headers = []); 96 | 97 | /** 98 | * Get logs statistics. 99 | * 100 | * @return array 101 | */ 102 | public function stats(); 103 | 104 | /** 105 | * Get logs statistics table. 106 | * 107 | * @param string|null $locale 108 | * 109 | * @return \Arcanedev\LogViewer\Tables\StatsTable 110 | */ 111 | public function statsTable($locale = null); 112 | 113 | /** 114 | * Delete the log. 115 | * 116 | * @param string $date 117 | * 118 | * @return bool 119 | * 120 | * @throws \Arcanedev\LogViewer\Exceptions\FilesystemException 121 | */ 122 | public function delete($date); 123 | 124 | /** 125 | * Clear the log files. 126 | * 127 | * @return bool 128 | */ 129 | public function clear(); 130 | 131 | /** 132 | * List the log files. 133 | * 134 | * @return array 135 | */ 136 | public function files(); 137 | 138 | /** 139 | * List the log files (only dates). 140 | * 141 | * @return array 142 | */ 143 | public function dates(); 144 | 145 | /** 146 | * Get logs count. 147 | * 148 | * @return int 149 | */ 150 | public function count(); 151 | 152 | /** 153 | * Get entries total from all logs. 154 | * 155 | * @param string $level 156 | * 157 | * @return int 158 | */ 159 | public function total($level = 'all'); 160 | 161 | /** 162 | * Get logs tree. 163 | * 164 | * @param bool|false $trans 165 | * 166 | * @return array 167 | */ 168 | public function tree($trans = false); 169 | 170 | /** 171 | * Get logs menu. 172 | * 173 | * @param bool|true $trans 174 | * 175 | * @return array 176 | */ 177 | public function menu($trans = true); 178 | 179 | /* ----------------------------------------------------------------- 180 | | Check Methods 181 | | ----------------------------------------------------------------- 182 | */ 183 | 184 | /** 185 | * Determine if the log folder is empty or not. 186 | * 187 | * @return bool 188 | */ 189 | public function isEmpty(); 190 | 191 | /* ----------------------------------------------------------------- 192 | | Other Methods 193 | | ----------------------------------------------------------------- 194 | */ 195 | 196 | /** 197 | * Get the LogViewer version. 198 | * 199 | * @return string 200 | */ 201 | public function version(); 202 | } 203 | -------------------------------------------------------------------------------- /src/Contracts/Patternable.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | interface Patternable 15 | { 16 | /* ----------------------------------------------------------------- 17 | | Getters & Setters 18 | | ----------------------------------------------------------------- 19 | */ 20 | 21 | /** 22 | * Get the log pattern. 23 | * 24 | * @return string 25 | */ 26 | public function getPattern(); 27 | 28 | /** 29 | * Set the log pattern. 30 | * 31 | * @param string $date 32 | * @param string $prefix 33 | * @param string $extension 34 | * 35 | * @return self 36 | */ 37 | public function setPattern( 38 | $prefix = Filesystem::PATTERN_PREFIX, 39 | $date = Filesystem::PATTERN_DATE, 40 | $extension = Filesystem::PATTERN_EXTENSION 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /src/Contracts/Table.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | interface Table 13 | { 14 | /* ----------------------------------------------------------------- 15 | | Getters & Setters 16 | | ----------------------------------------------------------------- 17 | */ 18 | 19 | /** 20 | * Get table header. 21 | * 22 | * @return array 23 | */ 24 | public function header(); 25 | 26 | /** 27 | * Get table rows. 28 | * 29 | * @return array 30 | */ 31 | public function rows(); 32 | 33 | /** 34 | * Get table footer. 35 | * 36 | * @return array 37 | */ 38 | public function footer(); 39 | } 40 | -------------------------------------------------------------------------------- /src/Contracts/Utilities/Factory.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | interface Factory extends Patternable 15 | { 16 | /* ----------------------------------------------------------------- 17 | | Getters & Setters 18 | | ----------------------------------------------------------------- 19 | */ 20 | 21 | /** 22 | * Get the filesystem instance. 23 | * 24 | * @return \Arcanedev\LogViewer\Contracts\Utilities\Filesystem 25 | */ 26 | public function getFilesystem(); 27 | 28 | /** 29 | * Set the filesystem instance. 30 | * 31 | * @param \Arcanedev\LogViewer\Contracts\Utilities\Filesystem $filesystem 32 | * 33 | * @return self 34 | */ 35 | public function setFilesystem(Filesystem $filesystem); 36 | 37 | /** 38 | * Get the log levels instance. 39 | * 40 | * @return \Arcanedev\LogViewer\Contracts\Utilities\LogLevels $levels 41 | */ 42 | public function getLevels(); 43 | 44 | /** 45 | * Set the log levels instance. 46 | * 47 | * @param \Arcanedev\LogViewer\Contracts\Utilities\LogLevels $levels 48 | * 49 | * @return self 50 | */ 51 | public function setLevels(LogLevels $levels); 52 | 53 | /** 54 | * Set the log storage path. 55 | * 56 | * @param string $storagePath 57 | * 58 | * @return self 59 | */ 60 | public function setPath($storagePath); 61 | 62 | /** 63 | * Get all logs. 64 | * 65 | * @return \Arcanedev\LogViewer\Entities\LogCollection 66 | */ 67 | public function logs(); 68 | 69 | /* ----------------------------------------------------------------- 70 | | Main Methods 71 | | ----------------------------------------------------------------- 72 | */ 73 | 74 | /** 75 | * Get all logs (alias). 76 | * 77 | * @see logs 78 | * 79 | * @return \Arcanedev\LogViewer\Entities\LogCollection 80 | */ 81 | public function all(); 82 | 83 | /** 84 | * Paginate all logs. 85 | * 86 | * @param int $perPage 87 | * 88 | * @return \Illuminate\Pagination\LengthAwarePaginator 89 | */ 90 | public function paginate($perPage = 30); 91 | 92 | /** 93 | * Get a log by date. 94 | * 95 | * @param string $date 96 | * 97 | * @return \Arcanedev\LogViewer\Entities\Log 98 | */ 99 | public function log($date); 100 | 101 | /** 102 | * Get a log by date (alias). 103 | * 104 | * @param string $date 105 | * 106 | * @return \Arcanedev\LogViewer\Entities\Log 107 | */ 108 | public function get($date); 109 | 110 | /** 111 | * Get log entries. 112 | * 113 | * @param string $date 114 | * @param string $level 115 | * 116 | * @return \Arcanedev\LogViewer\Entities\LogEntryCollection 117 | */ 118 | public function entries($date, $level = 'all'); 119 | 120 | /** 121 | * List the log files (dates). 122 | * 123 | * @return array 124 | */ 125 | public function dates(); 126 | 127 | /** 128 | * Get logs count. 129 | * 130 | * @return int 131 | */ 132 | public function count(); 133 | 134 | /** 135 | * Get total log entries. 136 | * 137 | * @param string $level 138 | * 139 | * @return int 140 | */ 141 | public function total($level = 'all'); 142 | 143 | /** 144 | * Get tree menu. 145 | * 146 | * @param bool $trans 147 | * 148 | * @return array 149 | */ 150 | public function tree($trans = false); 151 | 152 | /** 153 | * Get tree menu. 154 | * 155 | * @param bool $trans 156 | * 157 | * @return array 158 | */ 159 | public function menu($trans = true); 160 | 161 | /** 162 | * Get logs statistics. 163 | * 164 | * @return array 165 | */ 166 | public function stats(); 167 | 168 | /** 169 | * Get logs statistics table. 170 | * 171 | * @param string|null $locale 172 | * 173 | * @return \Arcanedev\LogViewer\Tables\StatsTable 174 | */ 175 | public function statsTable($locale = null); 176 | 177 | /* ----------------------------------------------------------------- 178 | | Check Methods 179 | | ----------------------------------------------------------------- 180 | */ 181 | 182 | /** 183 | * Determine if the log folder is empty or not. 184 | * 185 | * @return bool 186 | */ 187 | public function isEmpty(); 188 | } 189 | -------------------------------------------------------------------------------- /src/Contracts/Utilities/Filesystem.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | interface Filesystem extends Patternable 15 | { 16 | /* ----------------------------------------------------------------- 17 | | Constants 18 | | ----------------------------------------------------------------- 19 | */ 20 | 21 | const PATTERN_PREFIX = 'laravel-'; 22 | const PATTERN_DATE = '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]'; 23 | const PATTERN_EXTENSION = '.log'; 24 | 25 | /* ----------------------------------------------------------------- 26 | | Getters & Setters 27 | | ----------------------------------------------------------------- 28 | */ 29 | 30 | /** 31 | * Get the files instance. 32 | * 33 | * @return \Illuminate\Filesystem\Filesystem 34 | */ 35 | public function getInstance(); 36 | 37 | /** 38 | * Set the log storage path. 39 | * 40 | * @param string $storagePath 41 | * 42 | * @return $this 43 | */ 44 | public function setPath($storagePath); 45 | 46 | /** 47 | * Set the log date pattern. 48 | * 49 | * @param string $datePattern 50 | * 51 | * @return $this 52 | */ 53 | public function setDatePattern($datePattern); 54 | 55 | /** 56 | * Set the log prefix pattern. 57 | * 58 | * @param string $prefixPattern 59 | * 60 | * @return $this 61 | */ 62 | public function setPrefixPattern($prefixPattern); 63 | 64 | /** 65 | * Set the log extension. 66 | * 67 | * @param string $extension 68 | * 69 | * @return $this 70 | */ 71 | public function setExtension($extension); 72 | 73 | /* ----------------------------------------------------------------- 74 | | Main Methods 75 | | ----------------------------------------------------------------- 76 | */ 77 | 78 | /** 79 | * Get all log files. 80 | * 81 | * @return array 82 | */ 83 | public function all(); 84 | 85 | /** 86 | * Get all valid log files. 87 | * 88 | * @return array 89 | */ 90 | public function logs(); 91 | 92 | /** 93 | * List the log files (Only dates). 94 | * 95 | * @param bool $withPaths 96 | * 97 | * @return array 98 | */ 99 | public function dates($withPaths = false); 100 | 101 | /** 102 | * Read the log. 103 | * 104 | * @param string $date 105 | * 106 | * @return string 107 | * 108 | * @throws \Arcanedev\LogViewer\Exceptions\FilesystemException 109 | */ 110 | public function read($date); 111 | 112 | /** 113 | * Delete the log. 114 | * 115 | * @param string $date 116 | * 117 | * @return bool 118 | * 119 | * @throws \Arcanedev\LogViewer\Exceptions\FilesystemException 120 | */ 121 | public function delete(string $date); 122 | 123 | /** 124 | * Clear the log files. 125 | * 126 | * @return bool 127 | */ 128 | public function clear(); 129 | 130 | /** 131 | * Get the log file path. 132 | * 133 | * @param string $date 134 | * 135 | * @return string 136 | */ 137 | public function path($date); 138 | } 139 | -------------------------------------------------------------------------------- /src/Contracts/Utilities/LogChecker.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | interface LogChecker 15 | { 16 | /* ----------------------------------------------------------------- 17 | | Constants 18 | | ----------------------------------------------------------------- 19 | */ 20 | 21 | /** 22 | * @link http://laravel.com/docs/5.4/errors#configuration 23 | * @link https://github.com/Seldaek/monolog/blob/master/doc/02-handlers-formatters-processors.md#log-to-files-and-syslog 24 | */ 25 | const HANDLER_DAILY = 'daily'; 26 | const HANDLER_SINGLE = 'single'; 27 | const HANDLER_SYSLOG = 'syslog'; 28 | const HANDLER_ERRORLOG = 'errorlog'; 29 | 30 | /* ----------------------------------------------------------------- 31 | | Getters & Setters 32 | | ----------------------------------------------------------------- 33 | */ 34 | 35 | /** 36 | * Set the config instance. 37 | * 38 | * @param \Illuminate\Contracts\Config\Repository $config 39 | * 40 | * @return self 41 | */ 42 | public function setConfig(ConfigContract $config); 43 | 44 | /** 45 | * Set the Filesystem instance. 46 | * 47 | * @param \Arcanedev\LogViewer\Contracts\Utilities\Filesystem $filesystem 48 | * 49 | * @return self 50 | */ 51 | public function setFilesystem(Filesystem $filesystem); 52 | 53 | /* ----------------------------------------------------------------- 54 | | Main Methods 55 | | ----------------------------------------------------------------- 56 | */ 57 | 58 | /** 59 | * Get messages. 60 | * 61 | * @return array 62 | */ 63 | public function messages(); 64 | 65 | /** 66 | * Check passes ?? 67 | * 68 | * @return bool 69 | */ 70 | public function passes(); 71 | 72 | /** 73 | * Check fails ?? 74 | * 75 | * @return bool 76 | */ 77 | public function fails(); 78 | 79 | /** 80 | * Get the requirements 81 | * 82 | * @return array 83 | */ 84 | public function requirements(); 85 | } 86 | -------------------------------------------------------------------------------- /src/Contracts/Utilities/LogLevels.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | interface LogLevels 15 | { 16 | /* ----------------------------------------------------------------- 17 | | Getters & Setters 18 | | ----------------------------------------------------------------- 19 | */ 20 | 21 | /** 22 | * Set the Translator instance. 23 | * 24 | * @param \Illuminate\Translation\Translator $translator 25 | * 26 | * @return self 27 | */ 28 | public function setTranslator(Translator $translator); 29 | 30 | /** 31 | * Get the selected locale. 32 | * 33 | * @return string 34 | */ 35 | public function getLocale(); 36 | 37 | /** 38 | * Set the selected locale. 39 | * 40 | * @param string $locale 41 | * 42 | * @return self 43 | */ 44 | public function setLocale($locale); 45 | 46 | /* ----------------------------------------------------------------- 47 | | Main Methods 48 | | ----------------------------------------------------------------- 49 | */ 50 | 51 | /** 52 | * Get the log levels. 53 | * 54 | * @param bool $flip 55 | * 56 | * @return array 57 | */ 58 | public function lists($flip = false); 59 | 60 | /** 61 | * Get translated levels. 62 | * 63 | * @param string|null $locale 64 | * 65 | * @return array 66 | */ 67 | public function names($locale = null); 68 | 69 | /** 70 | * Get PSR log levels. 71 | * 72 | * @param bool $flip 73 | * 74 | * @return array 75 | */ 76 | public static function all($flip = false); 77 | 78 | /** 79 | * Get the translated level. 80 | * 81 | * @param string $key 82 | * @param string|null $locale 83 | * 84 | * @return string 85 | */ 86 | public function get($key, $locale = null); 87 | } 88 | -------------------------------------------------------------------------------- /src/Contracts/Utilities/LogMenu.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | interface LogMenu 16 | { 17 | /* ----------------------------------------------------------------- 18 | | Getters & Setters 19 | | ----------------------------------------------------------------- 20 | */ 21 | 22 | /** 23 | * Set the config instance. 24 | * 25 | * @param \Illuminate\Contracts\Config\Repository $config 26 | * 27 | * @return self 28 | */ 29 | public function setConfig(ConfigContract $config); 30 | 31 | /** 32 | * Set the log styler instance. 33 | * 34 | * @param \Arcanedev\LogViewer\Contracts\Utilities\LogStyler $styler 35 | * 36 | * @return self 37 | */ 38 | public function setLogStyler(LogStyler $styler); 39 | 40 | /* ----------------------------------------------------------------- 41 | | Main Methods 42 | | ----------------------------------------------------------------- 43 | */ 44 | 45 | /** 46 | * Make log menu. 47 | * 48 | * @param \Arcanedev\LogViewer\Entities\Log $log 49 | * @param bool $trans 50 | * 51 | * @return array 52 | */ 53 | public function make(Log $log, $trans = true); 54 | } 55 | -------------------------------------------------------------------------------- /src/Contracts/Utilities/LogStyler.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | interface LogStyler 13 | { 14 | /* ----------------------------------------------------------------- 15 | | Main Methods 16 | | ----------------------------------------------------------------- 17 | */ 18 | 19 | /** 20 | * Make level icon. 21 | * 22 | * @param string $level 23 | * @param string|null $default 24 | * 25 | * @return \Illuminate\Support\HtmlString 26 | */ 27 | public function icon($level, $default = null); 28 | 29 | /** 30 | * Get level color. 31 | * 32 | * @param string $level 33 | * @param string|null $default 34 | * 35 | * @return string 36 | */ 37 | public function color($level, $default = null); 38 | 39 | /** 40 | * Get strings to highlight. 41 | * 42 | * @param array $default 43 | * 44 | * @return array 45 | */ 46 | public function toHighlight(array $default = []); 47 | } 48 | -------------------------------------------------------------------------------- /src/Entities/Log.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class Log implements Arrayable, Jsonable, JsonSerializable 18 | { 19 | /* ----------------------------------------------------------------- 20 | | Properties 21 | | ----------------------------------------------------------------- 22 | */ 23 | 24 | /** @var string */ 25 | public $date; 26 | 27 | /** @var string */ 28 | private $path; 29 | 30 | /** @var \Arcanedev\LogViewer\Entities\LogEntryCollection */ 31 | private $entries; 32 | 33 | /** @var \SplFileInfo */ 34 | private $file; 35 | 36 | /* ----------------------------------------------------------------- 37 | | Constructor 38 | | ----------------------------------------------------------------- 39 | */ 40 | 41 | /** 42 | * Log constructor. 43 | * 44 | * @param string $date 45 | * @param string $path 46 | * @param string $raw 47 | */ 48 | public function __construct($date, $path, $raw) 49 | { 50 | $this->date = $date; 51 | $this->path = $path; 52 | $this->file = new SplFileInfo($path); 53 | $this->entries = LogEntryCollection::load($raw); 54 | } 55 | 56 | /* ----------------------------------------------------------------- 57 | | Getters & Setters 58 | | ----------------------------------------------------------------- 59 | */ 60 | 61 | /** 62 | * Get log path. 63 | * 64 | * @return string 65 | */ 66 | public function getPath() 67 | { 68 | return $this->path; 69 | } 70 | 71 | /** 72 | * Get file info. 73 | * 74 | * @return \SplFileInfo 75 | */ 76 | public function file() 77 | { 78 | return $this->file; 79 | } 80 | 81 | /** 82 | * Get file size. 83 | * 84 | * @return string 85 | */ 86 | public function size() 87 | { 88 | return $this->formatSize($this->file->getSize()); 89 | } 90 | 91 | /** 92 | * Get file creation date. 93 | * 94 | * @return \Carbon\Carbon 95 | */ 96 | public function createdAt() 97 | { 98 | return Carbon::createFromTimestamp($this->file()->getATime()); 99 | } 100 | 101 | /** 102 | * Get file modification date. 103 | * 104 | * @return \Carbon\Carbon 105 | */ 106 | public function updatedAt() 107 | { 108 | return Carbon::createFromTimestamp($this->file()->getMTime()); 109 | } 110 | 111 | /* ----------------------------------------------------------------- 112 | | Main Methods 113 | | ----------------------------------------------------------------- 114 | */ 115 | 116 | /** 117 | * Make a log object. 118 | * 119 | * @param string $date 120 | * @param string $path 121 | * @param string $raw 122 | * 123 | * @return self 124 | */ 125 | public static function make($date, $path, $raw) 126 | { 127 | return new self($date, $path, $raw); 128 | } 129 | 130 | /** 131 | * Get log entries. 132 | * 133 | * @param string $level 134 | * 135 | * @return \Arcanedev\LogViewer\Entities\LogEntryCollection 136 | */ 137 | public function entries($level = 'all') 138 | { 139 | return $level === 'all' 140 | ? $this->entries 141 | : $this->getByLevel($level); 142 | } 143 | 144 | /** 145 | * Get filtered log entries by level. 146 | * 147 | * @param string $level 148 | * 149 | * @return \Arcanedev\LogViewer\Entities\LogEntryCollection 150 | */ 151 | public function getByLevel($level) 152 | { 153 | return $this->entries->filterByLevel($level); 154 | } 155 | 156 | /** 157 | * Get log stats. 158 | * 159 | * @return array 160 | */ 161 | public function stats() 162 | { 163 | return $this->entries->stats(); 164 | } 165 | 166 | /** 167 | * Get the log navigation tree. 168 | * 169 | * @param bool $trans 170 | * 171 | * @return array 172 | */ 173 | public function tree($trans = false) 174 | { 175 | return $this->entries->tree($trans); 176 | } 177 | 178 | /** 179 | * Get log entries menu. 180 | * 181 | * @param bool $trans 182 | * 183 | * @return array 184 | */ 185 | public function menu($trans = true) 186 | { 187 | return log_menu()->make($this, $trans); 188 | } 189 | 190 | /* ----------------------------------------------------------------- 191 | | Convert Methods 192 | | ----------------------------------------------------------------- 193 | */ 194 | 195 | /** 196 | * Get the log as a plain array. 197 | * 198 | * @return array 199 | */ 200 | public function toArray() 201 | { 202 | return [ 203 | 'date' => $this->date, 204 | 'path' => $this->path, 205 | 'entries' => $this->entries->toArray() 206 | ]; 207 | } 208 | 209 | /** 210 | * Convert the object to its JSON representation. 211 | * 212 | * @param int $options 213 | * 214 | * @return string 215 | */ 216 | public function toJson($options = 0) 217 | { 218 | return json_encode($this->toArray(), $options); 219 | } 220 | 221 | /** 222 | * Serialize the log object to json data. 223 | * 224 | * @return array 225 | */ 226 | public function jsonSerialize(): array 227 | { 228 | return $this->toArray(); 229 | } 230 | 231 | /* ----------------------------------------------------------------- 232 | | Other Methods 233 | | ----------------------------------------------------------------- 234 | */ 235 | 236 | /** 237 | * Format the file size. 238 | * 239 | * @param int $bytes 240 | * @param int $precision 241 | * 242 | * @return string 243 | */ 244 | private function formatSize($bytes, $precision = 2) 245 | { 246 | $units = ['B', 'KB', 'MB', 'GB', 'TB']; 247 | 248 | $bytes = max($bytes, 0); 249 | $pow = floor(($bytes ? log($bytes) : 0) / log(1024)); 250 | $pow = min($pow, count($units) - 1); 251 | 252 | return round($bytes / pow(1024, $pow), $precision).' '.$units[$pow]; 253 | } 254 | } 255 | -------------------------------------------------------------------------------- /src/Entities/LogCollection.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class LogCollection extends LazyCollection 18 | { 19 | /* ----------------------------------------------------------------- 20 | | Properties 21 | | ----------------------------------------------------------------- 22 | */ 23 | 24 | /** @var \Arcanedev\LogViewer\Contracts\Utilities\Filesystem */ 25 | private $filesystem; 26 | 27 | /* ----------------------------------------------------------------- 28 | | Constructor 29 | | ----------------------------------------------------------------- 30 | */ 31 | 32 | /** 33 | * LogCollection constructor. 34 | * 35 | * @param mixed $source 36 | */ 37 | public function __construct($source = null) 38 | { 39 | $this->setFilesystem(app(FilesystemContract::class)); 40 | 41 | if (is_null($source)) 42 | $source = function () { 43 | foreach($this->filesystem->dates(true) as $date => $path) { 44 | yield $date => Log::make($date, $path, $this->filesystem->read($date)); 45 | } 46 | }; 47 | 48 | parent::__construct($source); 49 | } 50 | 51 | /* ----------------------------------------------------------------- 52 | | Getters & Setters 53 | | ----------------------------------------------------------------- 54 | */ 55 | 56 | /** 57 | * Set the filesystem instance. 58 | * 59 | * @param \Arcanedev\LogViewer\Contracts\Utilities\Filesystem $filesystem 60 | * 61 | * @return \Arcanedev\LogViewer\Entities\LogCollection 62 | */ 63 | public function setFilesystem(FilesystemContract $filesystem) 64 | { 65 | $this->filesystem = $filesystem; 66 | 67 | return $this; 68 | } 69 | 70 | /* ----------------------------------------------------------------- 71 | | Main Methods 72 | | ----------------------------------------------------------------- 73 | */ 74 | 75 | /** 76 | * Get a log. 77 | * 78 | * @param string $date 79 | * @param mixed|null $default 80 | * 81 | * @return \Arcanedev\LogViewer\Entities\Log 82 | * 83 | * @throws \Arcanedev\LogViewer\Exceptions\LogNotFoundException 84 | */ 85 | public function get($date, $default = null) 86 | { 87 | if ( ! $this->has($date)) 88 | throw LogNotFoundException::make($date); 89 | 90 | return parent::get($date, $default); 91 | } 92 | 93 | /** 94 | * Paginate logs. 95 | * 96 | * @param int $perPage 97 | * 98 | * @return \Illuminate\Pagination\LengthAwarePaginator 99 | */ 100 | public function paginate($perPage = 30) 101 | { 102 | $page = request()->get('page', 1); 103 | $path = request()->url(); 104 | 105 | return new LengthAwarePaginator( 106 | $this->forPage($page, $perPage), 107 | $this->count(), 108 | $perPage, 109 | $page, 110 | compact('path') 111 | ); 112 | } 113 | 114 | /** 115 | * Get a log (alias). 116 | * 117 | * @see get() 118 | * 119 | * @param string $date 120 | * 121 | * @return \Arcanedev\LogViewer\Entities\Log 122 | */ 123 | public function log($date) 124 | { 125 | return $this->get($date); 126 | } 127 | 128 | 129 | /** 130 | * Get log entries. 131 | * 132 | * @param string $date 133 | * @param string $level 134 | * 135 | * @return \Arcanedev\LogViewer\Entities\LogEntryCollection 136 | */ 137 | public function entries($date, $level = 'all') 138 | { 139 | return $this->get($date)->entries($level); 140 | } 141 | 142 | /** 143 | * Get logs statistics. 144 | * 145 | * @return array 146 | */ 147 | public function stats() 148 | { 149 | $stats = []; 150 | 151 | foreach ($this->all() as $date => $log) { 152 | /** @var \Arcanedev\LogViewer\Entities\Log $log */ 153 | $stats[$date] = $log->stats(); 154 | } 155 | 156 | return $stats; 157 | } 158 | 159 | /** 160 | * List the log files (dates). 161 | * 162 | * @return array 163 | */ 164 | public function dates() 165 | { 166 | return $this->keys()->toArray(); 167 | } 168 | 169 | /** 170 | * Get entries total. 171 | * 172 | * @param string $level 173 | * 174 | * @return int 175 | */ 176 | public function total($level = 'all') 177 | { 178 | return (int) $this->sum(function (Log $log) use ($level) { 179 | return $log->entries($level)->count(); 180 | }); 181 | } 182 | 183 | /** 184 | * Get logs tree. 185 | * 186 | * @param bool $trans 187 | * 188 | * @return array 189 | */ 190 | public function tree($trans = false) 191 | { 192 | $tree = []; 193 | 194 | foreach ($this->all() as $date => $log) { 195 | /** @var \Arcanedev\LogViewer\Entities\Log $log */ 196 | $tree[$date] = $log->tree($trans); 197 | } 198 | 199 | return $tree; 200 | } 201 | 202 | /** 203 | * Get logs menu. 204 | * 205 | * @param bool $trans 206 | * 207 | * @return array 208 | */ 209 | public function menu($trans = true) 210 | { 211 | $menu = []; 212 | 213 | foreach ($this->all() as $date => $log) { 214 | /** @var \Arcanedev\LogViewer\Entities\Log $log */ 215 | $menu[$date] = $log->menu($trans); 216 | } 217 | 218 | return $menu; 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /src/Entities/LogEntry.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class LogEntry implements Arrayable, Jsonable, JsonSerializable 18 | { 19 | /* ----------------------------------------------------------------- 20 | | Properties 21 | | ----------------------------------------------------------------- 22 | */ 23 | 24 | /** @var string */ 25 | public $env; 26 | 27 | /** @var string */ 28 | public $level; 29 | 30 | /** @var \Carbon\Carbon */ 31 | public $datetime; 32 | 33 | /** @var string */ 34 | public $header; 35 | 36 | /** @var string */ 37 | public $stack; 38 | 39 | /** @var array */ 40 | public $context = []; 41 | 42 | /* ----------------------------------------------------------------- 43 | | Constructor 44 | | ----------------------------------------------------------------- 45 | */ 46 | 47 | /** 48 | * Construct the log entry instance. 49 | * 50 | * @param string $level 51 | * @param string $header 52 | * @param string|null $stack 53 | */ 54 | public function __construct($level, $header, $stack = null) 55 | { 56 | $this->setLevel($level); 57 | $this->setHeader($header); 58 | $this->setStack($stack); 59 | } 60 | 61 | /* ----------------------------------------------------------------- 62 | | Getters & Setters 63 | | ----------------------------------------------------------------- 64 | */ 65 | 66 | /** 67 | * Set the entry level. 68 | * 69 | * @param string $level 70 | * 71 | * @return self 72 | */ 73 | private function setLevel($level) 74 | { 75 | $this->level = $level; 76 | 77 | return $this; 78 | } 79 | 80 | /** 81 | * Set the entry header. 82 | * 83 | * @param string $header 84 | * 85 | * @return self 86 | */ 87 | private function setHeader($header) 88 | { 89 | $this->setDatetime($this->extractDatetime($header)); 90 | 91 | $header = $this->cleanHeader($header); 92 | 93 | $this->header = trim($header); 94 | 95 | return $this; 96 | } 97 | 98 | /** 99 | * Set the context. 100 | * 101 | * @param array $context 102 | * 103 | * @return $this 104 | */ 105 | private function setContext(array $context) 106 | { 107 | $this->context = $context; 108 | 109 | return $this; 110 | } 111 | 112 | /** 113 | * Set entry environment. 114 | * 115 | * @param string $env 116 | * 117 | * @return self 118 | */ 119 | private function setEnv($env) 120 | { 121 | $this->env = head(explode('.', $env)); 122 | 123 | return $this; 124 | } 125 | 126 | /** 127 | * Set the entry date time. 128 | * 129 | * @param string $datetime 130 | * 131 | * @return \Arcanedev\LogViewer\Entities\LogEntry 132 | */ 133 | private function setDatetime($datetime) 134 | { 135 | $this->datetime = Carbon::createFromFormat('Y-m-d H:i:s', $datetime); 136 | 137 | return $this; 138 | } 139 | 140 | /** 141 | * Set the entry stack. 142 | * 143 | * @param string $stack 144 | * 145 | * @return self 146 | */ 147 | private function setStack($stack) 148 | { 149 | $this->stack = $stack; 150 | 151 | return $this; 152 | } 153 | 154 | /** 155 | * Get translated level name with icon. 156 | * 157 | * @return string 158 | */ 159 | public function level() 160 | { 161 | return $this->icon()->toHtml().' '.$this->name(); 162 | } 163 | 164 | /** 165 | * Get translated level name. 166 | * 167 | * @return string 168 | */ 169 | public function name() 170 | { 171 | return log_levels()->get($this->level); 172 | } 173 | 174 | /** 175 | * Get level icon. 176 | * 177 | * @return \Illuminate\Support\HtmlString 178 | */ 179 | public function icon() 180 | { 181 | return log_styler()->icon($this->level); 182 | } 183 | 184 | /** 185 | * Get the entry stack. 186 | * 187 | * @return string 188 | */ 189 | public function stack() 190 | { 191 | return trim(htmlentities($this->stack)); 192 | } 193 | 194 | /** 195 | * Get the entry context as json pretty print. 196 | */ 197 | public function context(int $options = JSON_PRETTY_PRINT): string 198 | { 199 | return json_encode($this->context, $options); 200 | } 201 | 202 | /* ----------------------------------------------------------------- 203 | | Check Methods 204 | | ----------------------------------------------------------------- 205 | */ 206 | 207 | /** 208 | * Check if same log level. 209 | * 210 | * @param string $level 211 | * 212 | * @return bool 213 | */ 214 | public function isSameLevel($level) 215 | { 216 | return $this->level === $level; 217 | } 218 | 219 | /* ----------------------------------------------------------------- 220 | | Convert Methods 221 | | ----------------------------------------------------------------- 222 | */ 223 | 224 | /** 225 | * Get the log entry as an array. 226 | * 227 | * @return array 228 | */ 229 | public function toArray() 230 | { 231 | return [ 232 | 'level' => $this->level, 233 | 'datetime' => $this->datetime->format('Y-m-d H:i:s'), 234 | 'header' => $this->header, 235 | 'stack' => $this->stack 236 | ]; 237 | } 238 | 239 | /** 240 | * Convert the log entry to its JSON representation. 241 | * 242 | * @param int $options 243 | * 244 | * @return string 245 | */ 246 | public function toJson($options = 0) 247 | { 248 | return json_encode($this->toArray(), $options); 249 | } 250 | 251 | /** 252 | * Serialize the log entry object to json data. 253 | */ 254 | public function jsonSerialize(): array 255 | { 256 | return $this->toArray(); 257 | } 258 | 259 | /* ----------------------------------------------------------------- 260 | | Check Methods 261 | | ----------------------------------------------------------------- 262 | */ 263 | 264 | /** 265 | * Check if the entry has a stack. 266 | * 267 | * @return bool 268 | */ 269 | public function hasStack() 270 | { 271 | return $this->stack !== "\n"; 272 | } 273 | 274 | /** 275 | * Check if the entry has a context. 276 | * 277 | * @return bool 278 | */ 279 | public function hasContext() 280 | { 281 | return ! empty($this->context); 282 | } 283 | 284 | /* ----------------------------------------------------------------- 285 | | Other Methods 286 | | ----------------------------------------------------------------- 287 | */ 288 | 289 | /** 290 | * Clean the entry header. 291 | * 292 | * @param string $header 293 | * 294 | * @return string 295 | */ 296 | private function cleanHeader($header) 297 | { 298 | // REMOVE THE DATE 299 | $header = preg_replace('/\['.LogParser::REGEX_DATETIME_PATTERN.'\][ ]/', '', $header); 300 | 301 | // EXTRACT ENV 302 | if (preg_match('/^[a-z]+.[A-Z]+:/', $header, $out)) { 303 | $this->setEnv($out[0]); 304 | $header = trim(str_replace($out[0], '', $header)); 305 | } 306 | 307 | // EXTRACT CONTEXT (Regex from https://stackoverflow.com/a/21995025) 308 | preg_match_all('/{(?:[^{}]|(?R))*}/x', $header, $out); 309 | if (isset($out[0][0]) && ! is_null($context = json_decode($out[0][0], true))) { 310 | $header = str_replace($out[0][0], '', $header); 311 | $this->setContext($context); 312 | } 313 | 314 | return $header; 315 | } 316 | 317 | /** 318 | * Extract datetime from the header. 319 | * 320 | * @param string $header 321 | * 322 | * @return string 323 | */ 324 | private function extractDatetime($header) 325 | { 326 | return preg_replace('/^\[('.LogParser::REGEX_DATETIME_PATTERN.')\].*/', '$1', $header); 327 | } 328 | } 329 | -------------------------------------------------------------------------------- /src/Entities/LogEntryCollection.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class LogEntryCollection extends LazyCollection 17 | { 18 | /* ----------------------------------------------------------------- 19 | | Main Methods 20 | | ----------------------------------------------------------------- 21 | */ 22 | 23 | /** 24 | * Load raw log entries. 25 | * 26 | * @param string $raw 27 | * 28 | * @return self 29 | */ 30 | public static function load($raw) 31 | { 32 | return new static(function () use ($raw) { 33 | foreach (LogParser::parse($raw) as $entry) { 34 | list($level, $header, $stack) = array_values($entry); 35 | 36 | yield new LogEntry($level, $header, $stack); 37 | } 38 | }); 39 | } 40 | 41 | /** 42 | * Paginate log entries. 43 | * 44 | * @param int $perPage 45 | * 46 | * @return \Illuminate\Pagination\LengthAwarePaginator 47 | */ 48 | public function paginate($perPage = 20) 49 | { 50 | $page = request()->get('page', 1); 51 | $path = request()->url(); 52 | 53 | return new LengthAwarePaginator( 54 | $this->forPage($page, $perPage), 55 | $this->count(), 56 | $perPage, 57 | $page, 58 | compact('path') 59 | ); 60 | } 61 | 62 | /** 63 | * Get filtered log entries by level. 64 | * 65 | * @param string $level 66 | * 67 | * @return self 68 | */ 69 | public function filterByLevel($level) 70 | { 71 | return $this->filter(function(LogEntry $entry) use ($level) { 72 | return $entry->isSameLevel($level); 73 | }); 74 | } 75 | 76 | /** 77 | * Get log entries stats. 78 | * 79 | * @return array 80 | */ 81 | public function stats() 82 | { 83 | $counters = $this->initStats(); 84 | 85 | foreach ($this->groupBy('level') as $level => $entries) { 86 | $counters[$level] = $count = count($entries); 87 | $counters['all'] += $count; 88 | } 89 | 90 | return $counters; 91 | } 92 | 93 | /** 94 | * Get the log entries navigation tree. 95 | * 96 | * @param bool|false $trans 97 | * 98 | * @return array 99 | */ 100 | public function tree($trans = false) 101 | { 102 | $tree = $this->stats(); 103 | 104 | array_walk($tree, function(&$count, $level) use ($trans) { 105 | $count = [ 106 | 'name' => $trans ? log_levels()->get($level) : $level, 107 | 'count' => $count, 108 | ]; 109 | }); 110 | 111 | return $tree; 112 | } 113 | 114 | /* ----------------------------------------------------------------- 115 | | Other Methods 116 | | ----------------------------------------------------------------- 117 | */ 118 | 119 | /** 120 | * Init stats counters. 121 | * 122 | * @return array 123 | */ 124 | private function initStats() 125 | { 126 | $levels = array_merge_recursive( 127 | ['all'], 128 | array_keys(log_viewer()->levels(true)) 129 | ); 130 | 131 | return array_map(function () { 132 | return 0; 133 | }, array_flip($levels)); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/Exceptions/FilesystemException.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class FilesystemException extends LogViewerException 13 | { 14 | public static function cannotDeleteLog() 15 | { 16 | return new static('There was an error deleting the log.'); 17 | } 18 | 19 | public static function invalidPath(string $path) 20 | { 21 | return new static("The log(s) could not be located at : $path"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Exceptions/LogNotFoundException.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class LogNotFoundException extends LogViewerException 13 | { 14 | /** 15 | * Make the exception. 16 | * 17 | * @param string $date 18 | * 19 | * @return static 20 | */ 21 | public static function make(string $date) 22 | { 23 | return new static("Log not found in this date [{$date}]"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Exceptions/LogViewerException.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class LogViewerException extends \Exception {} 13 | -------------------------------------------------------------------------------- /src/Helpers/LogParser.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class LogParser 16 | { 17 | /* ----------------------------------------------------------------- 18 | | Constants 19 | | ----------------------------------------------------------------- 20 | */ 21 | 22 | const REGEX_DATE_PATTERN = '\d{4}(-\d{2}){2}'; 23 | const REGEX_TIME_PATTERN = '\d{2}(:\d{2}){2}'; 24 | const REGEX_DATETIME_PATTERN = self::REGEX_DATE_PATTERN.' '.self::REGEX_TIME_PATTERN; 25 | 26 | /* ----------------------------------------------------------------- 27 | | Properties 28 | | ----------------------------------------------------------------- 29 | */ 30 | 31 | /** 32 | * Parsed data. 33 | * 34 | * @var array 35 | */ 36 | protected static $parsed = []; 37 | 38 | /* ----------------------------------------------------------------- 39 | | Main Methods 40 | | ----------------------------------------------------------------- 41 | */ 42 | 43 | /** 44 | * Parse file content. 45 | * 46 | * @param string $raw 47 | * 48 | * @return array 49 | */ 50 | public static function parse($raw) 51 | { 52 | static::$parsed = []; 53 | list($headings, $data) = static::parseRawData($raw); 54 | 55 | // @codeCoverageIgnoreStart 56 | if ( ! is_array($headings)) { 57 | return static::$parsed; 58 | } 59 | // @codeCoverageIgnoreEnd 60 | 61 | foreach ($headings as $heading) { 62 | for ($i = 0, $j = count($heading); $i < $j; $i++) { 63 | static::populateEntries($heading, $data, $i); 64 | } 65 | }; 66 | 67 | unset($headings, $data); 68 | 69 | return array_reverse(static::$parsed); 70 | } 71 | 72 | /* ----------------------------------------------------------------- 73 | | Other Methods 74 | | ----------------------------------------------------------------- 75 | */ 76 | 77 | /** 78 | * Extract the date. 79 | * 80 | * @param string $string 81 | * 82 | * @return string 83 | */ 84 | public static function extractDate(string $string): string 85 | { 86 | return preg_replace('/.*('.self::REGEX_DATE_PATTERN.').*/', '$1', $string); 87 | } 88 | 89 | /** 90 | * Parse raw data. 91 | * 92 | * @param string $raw 93 | * 94 | * @return array 95 | */ 96 | private static function parseRawData($raw) 97 | { 98 | $pattern = '/\['.self::REGEX_DATETIME_PATTERN.'\].*/'; 99 | preg_match_all($pattern, $raw, $headings); 100 | $data = preg_split($pattern, $raw); 101 | 102 | if ($data[0] < 1) { 103 | $trash = array_shift($data); 104 | unset($trash); 105 | } 106 | 107 | return [$headings, $data]; 108 | } 109 | 110 | /** 111 | * Populate entries. 112 | * 113 | * @param array $heading 114 | * @param array $data 115 | * @param int $key 116 | */ 117 | private static function populateEntries($heading, $data, $key) 118 | { 119 | foreach (LogLevels::all() as $level) { 120 | if (static::hasLogLevel($heading[$key], $level)) { 121 | static::$parsed[] = [ 122 | 'level' => $level, 123 | 'header' => $heading[$key], 124 | 'stack' => $data[$key] 125 | ]; 126 | } 127 | } 128 | } 129 | 130 | /** 131 | * Check if header has a log level. 132 | * 133 | * @param string $heading 134 | * @param string $level 135 | * 136 | * @return bool 137 | */ 138 | private static function hasLogLevel($heading, $level) 139 | { 140 | return Str::contains($heading, strtoupper(".{$level}:")); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/Http/Controllers/LogViewerController.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | class LogViewerController extends Controller 22 | { 23 | /* ----------------------------------------------------------------- 24 | | Properties 25 | | ----------------------------------------------------------------- 26 | */ 27 | 28 | /** 29 | * The log viewer instance 30 | * 31 | * @var \Arcanedev\LogViewer\Contracts\LogViewer 32 | */ 33 | protected $logViewer; 34 | 35 | /** @var int */ 36 | protected $perPage = 30; 37 | 38 | /** @var string */ 39 | protected $showRoute = 'log-viewer::logs.show'; 40 | 41 | /* ----------------------------------------------------------------- 42 | | Constructor 43 | | ----------------------------------------------------------------- 44 | */ 45 | 46 | /** 47 | * LogViewerController constructor. 48 | * 49 | * @param \Arcanedev\LogViewer\Contracts\LogViewer $logViewer 50 | */ 51 | public function __construct(LogViewerContract $logViewer) 52 | { 53 | $this->logViewer = $logViewer; 54 | $this->perPage = config('log-viewer.per-page', $this->perPage); 55 | $this->showRoute = config('log-viewer.route.show', $this->showRoute); 56 | } 57 | 58 | /* ----------------------------------------------------------------- 59 | | Main Methods 60 | | ----------------------------------------------------------------- 61 | */ 62 | 63 | /** 64 | * Show the dashboard. 65 | * 66 | * @return \Illuminate\View\View 67 | */ 68 | public function index() 69 | { 70 | $stats = $this->logViewer->statsTable(); 71 | $chartData = $this->prepareChartData($stats); 72 | $percents = $this->calcPercentages($stats->footer(), $stats->header()); 73 | 74 | return $this->view('dashboard', compact('chartData', 'percents')); 75 | } 76 | 77 | /** 78 | * List all logs. 79 | * 80 | * @param \Illuminate\Http\Request $request 81 | * 82 | * @return \Illuminate\View\View 83 | */ 84 | public function listLogs(Request $request) 85 | { 86 | $stats = $this->logViewer->statsTable(); 87 | $headers = $stats->header(); 88 | $rows = $this->paginate($stats->rows(), $request); 89 | 90 | return $this->view('logs', compact('headers', 'rows')); 91 | } 92 | 93 | /** 94 | * Show the log. 95 | * 96 | * @param \Illuminate\Http\Request $request 97 | * @param string $date 98 | * 99 | * @return \Illuminate\View\View 100 | */ 101 | public function show(Request $request, $date) 102 | { 103 | $level = 'all'; 104 | $log = $this->getLogOrFail($date); 105 | $query = $request->get('query'); 106 | $levels = $this->logViewer->levelsNames(); 107 | $entries = $log->entries($level)->paginate($this->perPage); 108 | 109 | return $this->view('show', compact('level', 'log', 'query', 'levels', 'entries')); 110 | } 111 | 112 | /** 113 | * Filter the log entries by level. 114 | * 115 | * @param \Illuminate\Http\Request $request 116 | * @param string $date 117 | * @param string $level 118 | * 119 | * @return \Illuminate\View\View|\Illuminate\Http\RedirectResponse 120 | */ 121 | public function showByLevel(Request $request, $date, $level) 122 | { 123 | if ($level === 'all') 124 | return redirect()->route($this->showRoute, [$date]); 125 | 126 | $log = $this->getLogOrFail($date); 127 | $query = $request->get('query'); 128 | $levels = $this->logViewer->levelsNames(); 129 | $entries = $this->logViewer->entries($date, $level)->paginate($this->perPage); 130 | 131 | return $this->view('show', compact('level', 'log', 'query', 'levels', 'entries')); 132 | } 133 | 134 | /** 135 | * Show the log with the search query. 136 | * 137 | * @param \Illuminate\Http\Request $request 138 | * @param string $date 139 | * @param string $level 140 | * 141 | * @return \Illuminate\View\View|\Illuminate\Http\RedirectResponse 142 | */ 143 | public function search(Request $request, $date, $level = 'all') 144 | { 145 | $query = $request->get('query'); 146 | 147 | if (is_null($query)) 148 | return redirect()->route($this->showRoute, [$date]); 149 | 150 | $log = $this->getLogOrFail($date); 151 | $levels = $this->logViewer->levelsNames(); 152 | $needles = array_map(function ($needle) { 153 | return Str::lower($needle); 154 | }, array_filter(explode(' ', $query))); 155 | $entries = $log->entries($level) 156 | ->unless(empty($needles), function (LogEntryCollection $entries) use ($needles) { 157 | return $entries->filter(function (LogEntry $entry) use ($needles) { 158 | foreach ([$entry->header, $entry->stack, $entry->context()] as $subject) { 159 | if (Str::containsAll(Str::lower($subject), $needles)) 160 | return true; 161 | } 162 | 163 | return false; 164 | }); 165 | }) 166 | ->paginate($this->perPage); 167 | 168 | return $this->view('show', compact('level', 'log', 'query', 'levels', 'entries')); 169 | } 170 | 171 | /** 172 | * Download the log 173 | * 174 | * @param string $date 175 | * 176 | * @return \Symfony\Component\HttpFoundation\BinaryFileResponse 177 | */ 178 | public function download($date) 179 | { 180 | return $this->logViewer->download($date); 181 | } 182 | 183 | /** 184 | * Delete a log. 185 | * 186 | * @param \Illuminate\Http\Request $request 187 | * 188 | * @return \Illuminate\Http\JsonResponse 189 | */ 190 | public function delete(Request $request) 191 | { 192 | abort_unless($request->ajax(), 405, 'Method Not Allowed'); 193 | 194 | $date = $request->input('date'); 195 | 196 | return response()->json([ 197 | 'result' => $this->logViewer->delete($date) ? 'success' : 'error' 198 | ]); 199 | } 200 | 201 | /* ----------------------------------------------------------------- 202 | | Other Methods 203 | | ----------------------------------------------------------------- 204 | */ 205 | 206 | /** 207 | * Get the evaluated view contents for the given view. 208 | * 209 | * @param string $view 210 | * @param array $data 211 | * @param array $mergeData 212 | * 213 | * @return \Illuminate\View\View 214 | */ 215 | protected function view($view, $data = [], $mergeData = []) 216 | { 217 | $theme = config('log-viewer.theme'); 218 | 219 | return view()->make("log-viewer::{$theme}.{$view}", $data, $mergeData); 220 | } 221 | 222 | /** 223 | * Paginate logs. 224 | * 225 | * @param array $data 226 | * @param \Illuminate\Http\Request $request 227 | * 228 | * @return \Illuminate\Pagination\LengthAwarePaginator 229 | */ 230 | protected function paginate(array $data, Request $request) 231 | { 232 | $data = new Collection($data); 233 | $page = $request->get('page', 1); 234 | $path = $request->url(); 235 | 236 | return new LengthAwarePaginator( 237 | $data->forPage($page, $this->perPage), 238 | $data->count(), 239 | $this->perPage, 240 | $page, 241 | compact('path') 242 | ); 243 | } 244 | 245 | /** 246 | * Get a log or fail 247 | * 248 | * @param string $date 249 | * 250 | * @return \Arcanedev\LogViewer\Entities\Log|null 251 | */ 252 | protected function getLogOrFail($date) 253 | { 254 | $log = null; 255 | 256 | try { 257 | $log = $this->logViewer->get($date); 258 | } 259 | catch (LogNotFoundException $e) { 260 | abort(404, $e->getMessage()); 261 | } 262 | 263 | return $log; 264 | } 265 | 266 | /** 267 | * Prepare chart data. 268 | * 269 | * @param \Arcanedev\LogViewer\Tables\StatsTable $stats 270 | * 271 | * @return string 272 | */ 273 | protected function prepareChartData(StatsTable $stats) 274 | { 275 | $totals = $stats->totals()->all(); 276 | 277 | return json_encode([ 278 | 'labels' => Arr::pluck($totals, 'label'), 279 | 'datasets' => [ 280 | [ 281 | 'data' => Arr::pluck($totals, 'value'), 282 | 'backgroundColor' => Arr::pluck($totals, 'color'), 283 | 'hoverBackgroundColor' => Arr::pluck($totals, 'highlight'), 284 | ], 285 | ], 286 | ]); 287 | } 288 | 289 | /** 290 | * Calculate the percentage. 291 | * 292 | * @param array $total 293 | * @param array $names 294 | * 295 | * @return array 296 | */ 297 | protected function calcPercentages(array $total, array $names) 298 | { 299 | $percents = []; 300 | $all = Arr::get($total, 'all'); 301 | 302 | foreach ($total as $level => $count) { 303 | $percents[$level] = [ 304 | 'name' => $names[$level], 305 | 'count' => $count, 306 | 'percent' => $all ? round(($count / $all) * 100, 2) : 0, 307 | ]; 308 | } 309 | 310 | return $percents; 311 | } 312 | } 313 | -------------------------------------------------------------------------------- /src/Http/Routes/LogViewerRoute.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class LogViewerRoute extends RouteRegistrar 16 | { 17 | /* ----------------------------------------------------------------- 18 | | Main Methods 19 | | ----------------------------------------------------------------- 20 | */ 21 | 22 | /** 23 | * Map all routes. 24 | */ 25 | public function map(): void 26 | { 27 | $attributes = (array) config('log-viewer.route.attributes'); 28 | 29 | $this->group($attributes, function() { 30 | $this->name('log-viewer::')->group(function () { 31 | $this->get('/', [LogViewerController::class, 'index']) 32 | ->name('dashboard'); // log-viewer::dashboard 33 | 34 | $this->mapLogsRoutes(); 35 | }); 36 | }); 37 | } 38 | 39 | /** 40 | * Map the logs routes. 41 | */ 42 | private function mapLogsRoutes(): void 43 | { 44 | $this->prefix('logs')->name('logs.')->group(function() { 45 | $this->get('/', [LogViewerController::class, 'listLogs']) 46 | ->name('list'); // log-viewer::logs.list 47 | 48 | $this->delete('delete', [LogViewerController::class, 'delete']) 49 | ->name('delete'); // log-viewer::logs.delete 50 | 51 | $this->prefix('{date}')->group(function() { 52 | $this->get('/', [LogViewerController::class, 'show']) 53 | ->name('show'); // log-viewer::logs.show 54 | 55 | $this->get('download', [LogViewerController::class, 'download']) 56 | ->name('download'); // log-viewer::logs.download 57 | 58 | $this->get('{level}', [LogViewerController::class, 'showByLevel']) 59 | ->name('filter'); // log-viewer::logs.filter 60 | 61 | $this->get('{level}/search', [LogViewerController::class, 'search']) 62 | ->name('search'); // log-viewer::logs.search 63 | }); 64 | }); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/LogViewer.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class LogViewer implements LogViewerContract 18 | { 19 | /* ----------------------------------------------------------------- 20 | | Constants 21 | | ----------------------------------------------------------------- 22 | */ 23 | 24 | /** 25 | * LogViewer Version 26 | */ 27 | const VERSION = '11.0.1'; 28 | 29 | /* ----------------------------------------------------------------- 30 | | Properties 31 | | ----------------------------------------------------------------- 32 | */ 33 | 34 | /** 35 | * The factory instance. 36 | * 37 | * @var \Arcanedev\LogViewer\Contracts\Utilities\Factory 38 | */ 39 | protected $factory; 40 | 41 | /** 42 | * The filesystem instance. 43 | * 44 | * @var \Arcanedev\LogViewer\Contracts\Utilities\Filesystem 45 | */ 46 | protected $filesystem; 47 | 48 | /** 49 | * The log levels instance. 50 | * 51 | * @var \Arcanedev\LogViewer\Contracts\Utilities\LogLevels 52 | */ 53 | protected $levels; 54 | 55 | /* ----------------------------------------------------------------- 56 | | Constructor 57 | | ----------------------------------------------------------------- 58 | */ 59 | 60 | /** 61 | * Create a new instance. 62 | * 63 | * @param \Arcanedev\LogViewer\Contracts\Utilities\Factory $factory 64 | * @param \Arcanedev\LogViewer\Contracts\Utilities\Filesystem $filesystem 65 | * @param \Arcanedev\LogViewer\Contracts\Utilities\LogLevels $levels 66 | */ 67 | public function __construct( 68 | FactoryContract $factory, 69 | FilesystemContract $filesystem, 70 | LogLevelsContract $levels 71 | ) { 72 | $this->factory = $factory; 73 | $this->filesystem = $filesystem; 74 | $this->levels = $levels; 75 | } 76 | 77 | /* ----------------------------------------------------------------- 78 | | Getters & Setters 79 | | ----------------------------------------------------------------- 80 | */ 81 | 82 | /** 83 | * Get the log levels. 84 | * 85 | * @param bool $flip 86 | * 87 | * @return array 88 | */ 89 | public function levels($flip = false) 90 | { 91 | return $this->levels->lists($flip); 92 | } 93 | 94 | /** 95 | * Get the translated log levels. 96 | * 97 | * @param string|null $locale 98 | * 99 | * @return array 100 | */ 101 | public function levelsNames($locale = null) 102 | { 103 | return $this->levels->names($locale); 104 | } 105 | 106 | /** 107 | * Set the log storage path. 108 | * 109 | * @param string $path 110 | * 111 | * @return self 112 | */ 113 | public function setPath($path) 114 | { 115 | $this->factory->setPath($path); 116 | 117 | return $this; 118 | } 119 | 120 | /** 121 | * Get the log pattern. 122 | * 123 | * @return string 124 | */ 125 | public function getPattern() 126 | { 127 | return $this->factory->getPattern(); 128 | } 129 | 130 | /** 131 | * Set the log pattern. 132 | * 133 | * @param string $date 134 | * @param string $prefix 135 | * @param string $extension 136 | * 137 | * @return self 138 | */ 139 | public function setPattern( 140 | $prefix = FilesystemContract::PATTERN_PREFIX, 141 | $date = FilesystemContract::PATTERN_DATE, 142 | $extension = FilesystemContract::PATTERN_EXTENSION 143 | ) { 144 | $this->factory->setPattern($prefix, $date, $extension); 145 | 146 | return $this; 147 | } 148 | 149 | /* ----------------------------------------------------------------- 150 | | Main Methods 151 | | ----------------------------------------------------------------- 152 | */ 153 | 154 | /** 155 | * Get all logs. 156 | * 157 | * @return \Arcanedev\LogViewer\Entities\LogCollection 158 | */ 159 | public function all() 160 | { 161 | return $this->factory->all(); 162 | } 163 | 164 | /** 165 | * Paginate all logs. 166 | * 167 | * @param int $perPage 168 | * 169 | * @return \Illuminate\Pagination\LengthAwarePaginator 170 | */ 171 | public function paginate($perPage = 30) 172 | { 173 | return $this->factory->paginate($perPage); 174 | } 175 | 176 | /** 177 | * Get a log. 178 | * 179 | * @param string $date 180 | * 181 | * @return \Arcanedev\LogViewer\Entities\Log 182 | */ 183 | public function get($date) 184 | { 185 | return $this->factory->log($date); 186 | } 187 | 188 | /** 189 | * Get the log entries. 190 | * 191 | * @param string $date 192 | * @param string $level 193 | * 194 | * @return \Arcanedev\LogViewer\Entities\LogEntryCollection 195 | */ 196 | public function entries($date, $level = 'all') 197 | { 198 | return $this->factory->entries($date, $level); 199 | } 200 | 201 | /** 202 | * Download a log file. 203 | * 204 | * @param string $date 205 | * @param string|null $filename 206 | * @param array $headers 207 | * 208 | * @return \Symfony\Component\HttpFoundation\BinaryFileResponse 209 | */ 210 | public function download($date, $filename = null, $headers = []) 211 | { 212 | if (is_null($filename)) { 213 | $filename = sprintf( 214 | "%s{$date}.%s", 215 | config('log-viewer.download.prefix', 'laravel-'), 216 | config('log-viewer.download.extension', 'log') 217 | ); 218 | } 219 | 220 | $path = $this->filesystem->path($date); 221 | 222 | return response()->download($path, $filename, $headers); 223 | } 224 | 225 | /** 226 | * Get logs statistics. 227 | * 228 | * @return array 229 | */ 230 | public function stats() 231 | { 232 | return $this->factory->stats(); 233 | } 234 | 235 | /** 236 | * Get logs statistics table. 237 | * 238 | * @param string|null $locale 239 | * 240 | * @return \Arcanedev\LogViewer\Tables\StatsTable 241 | */ 242 | public function statsTable($locale = null) 243 | { 244 | return $this->factory->statsTable($locale); 245 | } 246 | 247 | /** 248 | * Delete the log. 249 | * 250 | * @param string $date 251 | * 252 | * @return bool 253 | */ 254 | public function delete($date) 255 | { 256 | return $this->filesystem->delete($date); 257 | } 258 | 259 | /** 260 | * Clear the log files. 261 | * 262 | * @return bool 263 | */ 264 | public function clear() 265 | { 266 | return $this->filesystem->clear(); 267 | } 268 | 269 | /** 270 | * Get all valid log files. 271 | * 272 | * @return array 273 | */ 274 | public function files() 275 | { 276 | return $this->filesystem->logs(); 277 | } 278 | 279 | /** 280 | * List the log files (only dates). 281 | * 282 | * @return array 283 | */ 284 | public function dates() 285 | { 286 | return $this->factory->dates(); 287 | } 288 | 289 | /** 290 | * Get logs count. 291 | * 292 | * @return int 293 | */ 294 | public function count() 295 | { 296 | return $this->factory->count(); 297 | } 298 | 299 | /** 300 | * Get entries total from all logs. 301 | * 302 | * @param string $level 303 | * 304 | * @return int 305 | */ 306 | public function total($level = 'all') 307 | { 308 | return $this->factory->total($level); 309 | } 310 | 311 | /** 312 | * Get logs tree. 313 | * 314 | * @param bool $trans 315 | * 316 | * @return array 317 | */ 318 | public function tree($trans = false) 319 | { 320 | return $this->factory->tree($trans); 321 | } 322 | 323 | /** 324 | * Get logs menu. 325 | * 326 | * @param bool $trans 327 | * 328 | * @return array 329 | */ 330 | public function menu($trans = true) 331 | { 332 | return $this->factory->menu($trans); 333 | } 334 | 335 | /* ----------------------------------------------------------------- 336 | | Check Methods 337 | | ----------------------------------------------------------------- 338 | */ 339 | 340 | /** 341 | * Determine if the log folder is empty or not. 342 | * 343 | * @return bool 344 | */ 345 | public function isEmpty() 346 | { 347 | return $this->factory->isEmpty(); 348 | } 349 | 350 | /* ----------------------------------------------------------------- 351 | | Other Methods 352 | | ----------------------------------------------------------------- 353 | */ 354 | 355 | /** 356 | * Get the LogViewer version. 357 | * 358 | * @return string 359 | */ 360 | public function version() 361 | { 362 | return self::VERSION; 363 | } 364 | } 365 | -------------------------------------------------------------------------------- /src/LogViewerServiceProvider.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class LogViewerServiceProvider extends PackageServiceProvider 15 | { 16 | /* ----------------------------------------------------------------- 17 | | Properties 18 | | ----------------------------------------------------------------- 19 | */ 20 | 21 | /** 22 | * Package name. 23 | * 24 | * @var string 25 | */ 26 | protected $package = 'log-viewer'; 27 | 28 | /* ----------------------------------------------------------------- 29 | | Main Methods 30 | | ----------------------------------------------------------------- 31 | */ 32 | 33 | /** 34 | * Register the service provider. 35 | */ 36 | public function register(): void 37 | { 38 | parent::register(); 39 | 40 | $this->registerConfig(); 41 | 42 | $this->booted(function () { 43 | $this->registerProvider(Providers\RouteServiceProvider::class); 44 | }); 45 | 46 | $this->registerCommands([ 47 | Commands\PublishCommand::class, 48 | Commands\StatsCommand::class, 49 | Commands\CheckCommand::class, 50 | Commands\ClearCommand::class, 51 | ]); 52 | } 53 | 54 | /** 55 | * Boot the service provider. 56 | */ 57 | public function boot(): void 58 | { 59 | $this->loadTranslations(); 60 | $this->loadViews(); 61 | 62 | if ($this->app->runningInConsole()) { 63 | $this->publishConfig(); 64 | $this->publishTranslations(); 65 | $this->publishViews(); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Providers/DeferredServicesProvider.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | class DeferredServicesProvider extends ServiceProvider implements DeferrableProvider 25 | { 26 | /* ----------------------------------------------------------------- 27 | | Main Methods 28 | | ----------------------------------------------------------------- 29 | */ 30 | 31 | /** 32 | * Register the service provider. 33 | */ 34 | public function register(): void 35 | { 36 | $this->registerLogViewer(); 37 | $this->registerLogLevels(); 38 | $this->registerStyler(); 39 | $this->registerLogMenu(); 40 | $this->registerFilesystem(); 41 | $this->registerFactory(); 42 | $this->registerChecker(); 43 | } 44 | 45 | /** 46 | * Get the services provided by the provider. 47 | * 48 | * @return array 49 | */ 50 | public function provides(): array 51 | { 52 | return [ 53 | LogViewerContract::class, 54 | LogLevelsContract::class, 55 | LogStylerContract::class, 56 | LogMenuContract::class, 57 | FilesystemContract::class, 58 | FactoryContract::class, 59 | LogCheckerContract::class, 60 | ]; 61 | } 62 | 63 | /* ----------------------------------------------------------------- 64 | | LogViewer Utilities 65 | | ----------------------------------------------------------------- 66 | */ 67 | 68 | /** 69 | * Register the log viewer service. 70 | */ 71 | private function registerLogViewer(): void 72 | { 73 | $this->singleton(LogViewerContract::class, LogViewer::class); 74 | } 75 | 76 | /** 77 | * Register the log levels. 78 | */ 79 | private function registerLogLevels(): void 80 | { 81 | $this->singleton(LogLevelsContract::class, function ($app) { 82 | return new Utilities\LogLevels( 83 | $app['translator'], 84 | $app['config']->get('log-viewer.locale') 85 | ); 86 | }); 87 | } 88 | 89 | /** 90 | * Register the log styler. 91 | */ 92 | private function registerStyler(): void 93 | { 94 | $this->singleton(LogStylerContract::class, Utilities\LogStyler::class); 95 | } 96 | 97 | /** 98 | * Register the log menu builder. 99 | */ 100 | private function registerLogMenu(): void 101 | { 102 | $this->singleton(LogMenuContract::class, Utilities\LogMenu::class); 103 | } 104 | 105 | /** 106 | * Register the log filesystem. 107 | */ 108 | private function registerFilesystem(): void 109 | { 110 | $this->singleton(FilesystemContract::class, function ($app) { 111 | /** @var \Illuminate\Config\Repository $config */ 112 | $config = $app['config']; 113 | $filesystem = new Utilities\Filesystem($app['files'], $config->get('log-viewer.storage-path')); 114 | 115 | return $filesystem->setPattern( 116 | $config->get('log-viewer.pattern.prefix', FilesystemContract::PATTERN_PREFIX), 117 | $config->get('log-viewer.pattern.date', FilesystemContract::PATTERN_DATE), 118 | $config->get('log-viewer.pattern.extension', FilesystemContract::PATTERN_EXTENSION) 119 | ); 120 | }); 121 | } 122 | 123 | /** 124 | * Register the log factory class. 125 | */ 126 | private function registerFactory(): void 127 | { 128 | $this->singleton(FactoryContract::class, Utilities\Factory::class); 129 | } 130 | 131 | /** 132 | * Register the log checker service. 133 | */ 134 | private function registerChecker(): void 135 | { 136 | $this->singleton(LogCheckerContract::class, Utilities\LogChecker::class); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/Providers/RouteServiceProvider.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class RouteServiceProvider extends ServiceProvider 16 | { 17 | /* ----------------------------------------------------------------- 18 | | Getters & Setters 19 | | ----------------------------------------------------------------- 20 | */ 21 | 22 | /** 23 | * Check if routes is enabled 24 | * 25 | * @return bool 26 | */ 27 | public function isEnabled(): bool 28 | { 29 | return (bool) $this->config('enabled', false); 30 | } 31 | 32 | /* ----------------------------------------------------------------- 33 | | Main Methods 34 | | ----------------------------------------------------------------- 35 | */ 36 | 37 | /** 38 | * Boot the service provider. 39 | */ 40 | public function boot(): void 41 | { 42 | if ($this->isEnabled()) { 43 | $this->routes(function () { 44 | static::mapRouteClasses([LogViewerRoute::class]); 45 | }); 46 | } 47 | } 48 | 49 | /* ----------------------------------------------------------------- 50 | | Other Methods 51 | | ----------------------------------------------------------------- 52 | */ 53 | 54 | /** 55 | * Get config value by key 56 | * 57 | * @param string $key 58 | * @param mixed|null $default 59 | * 60 | * @return mixed 61 | */ 62 | private function config($key, $default = null) 63 | { 64 | return $this->app['config']->get("log-viewer.route.$key", $default); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Tables/AbstractTable.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | abstract class AbstractTable implements TableContract 16 | { 17 | /* ----------------------------------------------------------------- 18 | | Properties 19 | | ----------------------------------------------------------------- 20 | */ 21 | 22 | /** @var array */ 23 | private $header = []; 24 | 25 | /** @var array */ 26 | private $rows = []; 27 | 28 | /** @var array */ 29 | private $footer = []; 30 | 31 | /** @var \Arcanedev\LogViewer\Contracts\Utilities\LogLevels */ 32 | protected $levels; 33 | 34 | /** @var string|null */ 35 | protected $locale; 36 | 37 | /** @var array */ 38 | private $data = []; 39 | 40 | /* ----------------------------------------------------------------- 41 | | Constructor 42 | | ----------------------------------------------------------------- 43 | */ 44 | 45 | /** 46 | * Create a table instance. 47 | * 48 | * @param array $data 49 | * @param \Arcanedev\LogViewer\Contracts\Utilities\LogLevels $levels 50 | * @param string|null $locale 51 | */ 52 | public function __construct(array $data, LogLevelsContract $levels, $locale = null) 53 | { 54 | $this->setLevels($levels); 55 | $this->setLocale(is_null($locale) ? config('log-viewer.locale') : $locale); 56 | $this->setData($data); 57 | $this->init(); 58 | } 59 | 60 | /* ----------------------------------------------------------------- 61 | | Getters & Setters 62 | | ----------------------------------------------------------------- 63 | */ 64 | 65 | /** 66 | * Set LogLevels instance. 67 | * 68 | * @param \Arcanedev\LogViewer\Contracts\Utilities\LogLevels $levels 69 | * 70 | * @return $this 71 | */ 72 | protected function setLevels(LogLevelsContract $levels) 73 | { 74 | $this->levels = $levels; 75 | 76 | return $this; 77 | } 78 | 79 | /** 80 | * Set table locale. 81 | * 82 | * @param string|null $locale 83 | * 84 | * @return $this 85 | */ 86 | protected function setLocale($locale) 87 | { 88 | if (is_null($locale) || $locale === 'auto') { 89 | $locale = app()->getLocale(); 90 | } 91 | 92 | $this->locale = $locale; 93 | 94 | return $this; 95 | } 96 | 97 | /** 98 | * Get table header. 99 | * 100 | * @return array 101 | */ 102 | public function header() 103 | { 104 | return $this->header; 105 | } 106 | 107 | /** 108 | * Get table rows. 109 | * 110 | * @return array 111 | */ 112 | public function rows() 113 | { 114 | return $this->rows; 115 | } 116 | 117 | /** 118 | * Get table footer. 119 | * 120 | * @return array 121 | */ 122 | public function footer() 123 | { 124 | return $this->footer; 125 | } 126 | 127 | /** 128 | * Get raw data. 129 | * 130 | * @return array 131 | */ 132 | public function data() 133 | { 134 | return $this->data; 135 | } 136 | 137 | /** 138 | * Set table data. 139 | * 140 | * @param array $data 141 | * 142 | * @return $this 143 | */ 144 | private function setData(array $data) 145 | { 146 | $this->data = $data; 147 | 148 | return $this; 149 | } 150 | 151 | /* ----------------------------------------------------------------- 152 | | Main Methods 153 | | ----------------------------------------------------------------- 154 | */ 155 | 156 | /** 157 | * Prepare the table. 158 | */ 159 | private function init() 160 | { 161 | $this->header = $this->prepareHeader($this->data); 162 | $this->rows = $this->prepareRows($this->data); 163 | $this->footer = $this->prepareFooter($this->data); 164 | } 165 | 166 | /** 167 | * Prepare table header. 168 | * 169 | * @param array $data 170 | * 171 | * @return array 172 | */ 173 | abstract protected function prepareHeader(array $data); 174 | 175 | /** 176 | * Prepare table rows. 177 | * 178 | * @param array $data 179 | * 180 | * @return array 181 | */ 182 | abstract protected function prepareRows(array $data); 183 | 184 | /** 185 | * Prepare table footer. 186 | * 187 | * @param array $data 188 | * 189 | * @return array 190 | */ 191 | abstract protected function prepareFooter(array $data); 192 | 193 | /* ----------------------------------------------------------------- 194 | | Other Methods 195 | | ----------------------------------------------------------------- 196 | */ 197 | 198 | /** 199 | * Get log level color. 200 | * 201 | * @param string $level 202 | * 203 | * @return string 204 | */ 205 | protected function color($level) 206 | { 207 | return log_styler()->color($level); 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /src/Tables/StatsTable.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class StatsTable extends AbstractTable 16 | { 17 | /* ----------------------------------------------------------------- 18 | | Main Methods 19 | | ----------------------------------------------------------------- 20 | */ 21 | 22 | /** 23 | * Make a stats table instance. 24 | * 25 | * @param array $data 26 | * @param \Arcanedev\LogViewer\Contracts\Utilities\LogLevels $levels 27 | * @param string|null $locale 28 | * 29 | * @return $this 30 | */ 31 | public static function make(array $data, LogLevelsContract $levels, $locale = null) 32 | { 33 | return new static($data, $levels, $locale); 34 | } 35 | 36 | /* ----------------------------------------------------------------- 37 | | Other Methods 38 | | ----------------------------------------------------------------- 39 | */ 40 | 41 | /** 42 | * Prepare table header. 43 | * 44 | * @param array $data 45 | * 46 | * @return array 47 | */ 48 | protected function prepareHeader(array $data) 49 | { 50 | return array_merge_recursive( 51 | [ 52 | 'date' => __('Date'), 53 | 'all' => __('All'), 54 | ], 55 | $this->levels->names($this->locale) 56 | ); 57 | } 58 | 59 | /** 60 | * Prepare table rows. 61 | * 62 | * @param array $data 63 | * 64 | * @return array 65 | */ 66 | protected function prepareRows(array $data) 67 | { 68 | $rows = []; 69 | 70 | foreach ($data as $date => $levels) { 71 | $rows[$date] = array_merge(compact('date'), $levels); 72 | } 73 | 74 | return $rows; 75 | } 76 | 77 | /** 78 | * Prepare table footer. 79 | * 80 | * @param array $data 81 | * 82 | * @return array 83 | */ 84 | protected function prepareFooter(array $data) 85 | { 86 | $footer = []; 87 | 88 | foreach ($data as $date => $levels) { 89 | foreach ($levels as $level => $count) { 90 | if ( ! isset($footer[$level])) { 91 | $footer[$level] = 0; 92 | } 93 | 94 | $footer[$level] += $count; 95 | } 96 | } 97 | 98 | return $footer; 99 | } 100 | 101 | /** 102 | * Get totals. 103 | * 104 | * @param string|null $locale 105 | * 106 | * @return \Illuminate\Support\Collection 107 | */ 108 | public function totals($locale = null) 109 | { 110 | $totals = Collection::make(); 111 | 112 | foreach (Arr::except($this->footer(), 'all') as $level => $count) { 113 | $totals->put($level, [ 114 | 'label' => log_levels()->get($level, $locale), 115 | 'value' => $count, 116 | 'color' => $this->color($level), 117 | 'highlight' => $this->color($level), 118 | ]); 119 | } 120 | 121 | return $totals; 122 | } 123 | 124 | /** 125 | * Get json totals data. 126 | * 127 | * @param string|null $locale 128 | * 129 | * @return string 130 | */ 131 | public function totalsJson($locale = null) 132 | { 133 | return $this->totals($locale)->toJson(JSON_PRETTY_PRINT); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/Utilities/Factory.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | class Factory implements FactoryContract 21 | { 22 | /* ----------------------------------------------------------------- 23 | | Properties 24 | | ----------------------------------------------------------------- 25 | */ 26 | 27 | /** 28 | * The filesystem instance. 29 | * 30 | * @var \Arcanedev\LogViewer\Contracts\Utilities\Filesystem 31 | */ 32 | protected $filesystem; 33 | 34 | /** 35 | * The log levels instance. 36 | * 37 | * @var \Arcanedev\LogViewer\Contracts\Utilities\LogLevels 38 | */ 39 | private $levels; 40 | 41 | /* ----------------------------------------------------------------- 42 | | Constructor 43 | | ----------------------------------------------------------------- 44 | */ 45 | 46 | /** 47 | * Create a new instance. 48 | * 49 | * @param \Arcanedev\LogViewer\Contracts\Utilities\Filesystem $filesystem 50 | * @param \Arcanedev\LogViewer\Contracts\Utilities\LogLevels $levels 51 | */ 52 | public function __construct(FilesystemContract $filesystem, LogLevelsContract $levels) { 53 | $this->setFilesystem($filesystem); 54 | $this->setLevels($levels); 55 | } 56 | 57 | /* ----------------------------------------------------------------- 58 | | Getter & Setters 59 | | ----------------------------------------------------------------- 60 | */ 61 | 62 | /** 63 | * Get the filesystem instance. 64 | * 65 | * @return \Arcanedev\LogViewer\Contracts\Utilities\Filesystem 66 | */ 67 | public function getFilesystem() 68 | { 69 | return $this->filesystem; 70 | } 71 | 72 | /** 73 | * Set the filesystem instance. 74 | * 75 | * @param \Arcanedev\LogViewer\Contracts\Utilities\Filesystem $filesystem 76 | * 77 | * @return self 78 | */ 79 | public function setFilesystem(FilesystemContract $filesystem) 80 | { 81 | $this->filesystem = $filesystem; 82 | 83 | return $this; 84 | } 85 | 86 | /** 87 | * Get the log levels instance. 88 | * 89 | * @return \Arcanedev\LogViewer\Contracts\Utilities\LogLevels 90 | */ 91 | public function getLevels() 92 | { 93 | return $this->levels; 94 | } 95 | 96 | /** 97 | * Set the log levels instance. 98 | * 99 | * @param \Arcanedev\LogViewer\Contracts\Utilities\LogLevels $levels 100 | * 101 | * @return self 102 | */ 103 | public function setLevels(LogLevelsContract $levels) 104 | { 105 | $this->levels = $levels; 106 | 107 | return $this; 108 | } 109 | 110 | /** 111 | * Set the log storage path. 112 | * 113 | * @param string $storagePath 114 | * 115 | * @return self 116 | */ 117 | public function setPath($storagePath) 118 | { 119 | $this->filesystem->setPath($storagePath); 120 | 121 | return $this; 122 | } 123 | 124 | /** 125 | * Get the log pattern. 126 | * 127 | * @return string 128 | */ 129 | public function getPattern() 130 | { 131 | return $this->filesystem->getPattern(); 132 | } 133 | 134 | /** 135 | * Set the log pattern. 136 | * 137 | * @param string $date 138 | * @param string $prefix 139 | * @param string $extension 140 | * 141 | * @return self 142 | */ 143 | public function setPattern( 144 | $prefix = FilesystemContract::PATTERN_PREFIX, 145 | $date = FilesystemContract::PATTERN_DATE, 146 | $extension = FilesystemContract::PATTERN_EXTENSION 147 | ) { 148 | $this->filesystem->setPattern($prefix, $date, $extension); 149 | 150 | return $this; 151 | } 152 | 153 | /** 154 | * Get all logs. 155 | * 156 | * @return \Arcanedev\LogViewer\Entities\LogCollection 157 | */ 158 | public function logs() 159 | { 160 | return (new LogCollection)->setFilesystem($this->filesystem); 161 | } 162 | 163 | /* ----------------------------------------------------------------- 164 | | Main Methods 165 | | ----------------------------------------------------------------- 166 | */ 167 | 168 | /** 169 | * Get all logs (alias). 170 | * 171 | * @see logs 172 | * 173 | * @return \Arcanedev\LogViewer\Entities\LogCollection 174 | */ 175 | public function all() 176 | { 177 | return $this->logs(); 178 | } 179 | 180 | /** 181 | * Paginate all logs. 182 | * 183 | * @param int $perPage 184 | * 185 | * @return \Illuminate\Pagination\LengthAwarePaginator 186 | */ 187 | public function paginate($perPage = 30) 188 | { 189 | return $this->logs()->paginate($perPage); 190 | } 191 | 192 | /** 193 | * Get a log by date. 194 | * 195 | * @param string $date 196 | * 197 | * @return \Arcanedev\LogViewer\Entities\Log 198 | */ 199 | public function log($date) 200 | { 201 | $dates = $this->filesystem->dates(true); 202 | if (!isset($dates[$date])) { 203 | throw new LogNotFoundException("Log not found in this date [$date]"); 204 | } 205 | 206 | return new Log($date, $dates[$date], $this->filesystem->read($date)); 207 | } 208 | 209 | /** 210 | * Get a log by date (alias). 211 | * 212 | * @param string $date 213 | * 214 | * @return \Arcanedev\LogViewer\Entities\Log 215 | */ 216 | public function get($date) 217 | { 218 | return $this->log($date); 219 | } 220 | 221 | /** 222 | * Get log entries. 223 | * 224 | * @param string $date 225 | * @param string $level 226 | * 227 | * @return \Arcanedev\LogViewer\Entities\LogEntryCollection 228 | */ 229 | public function entries($date, $level = 'all') 230 | { 231 | return $this->log($date)->entries($level); 232 | } 233 | 234 | /** 235 | * Get logs statistics. 236 | * 237 | * @return array 238 | */ 239 | public function stats() 240 | { 241 | return $this->logs()->stats(); 242 | } 243 | 244 | /** 245 | * Get logs statistics table. 246 | * 247 | * @param string|null $locale 248 | * 249 | * @return \Arcanedev\LogViewer\Tables\StatsTable 250 | */ 251 | public function statsTable($locale = null) 252 | { 253 | return StatsTable::make($this->stats(), $this->levels, $locale); 254 | } 255 | 256 | /** 257 | * List the log files (dates). 258 | * 259 | * @return array 260 | */ 261 | public function dates() 262 | { 263 | return $this->filesystem->dates(); 264 | } 265 | 266 | /** 267 | * Get logs count. 268 | * 269 | * @return int 270 | */ 271 | public function count() 272 | { 273 | return $this->logs()->count(); 274 | } 275 | 276 | /** 277 | * Get total log entries. 278 | * 279 | * @param string $level 280 | * 281 | * @return int 282 | */ 283 | public function total($level = 'all') 284 | { 285 | return $this->logs()->total($level); 286 | } 287 | 288 | /** 289 | * Get tree menu. 290 | * 291 | * @param bool $trans 292 | * 293 | * @return array 294 | */ 295 | public function tree($trans = false) 296 | { 297 | return $this->logs()->tree($trans); 298 | } 299 | 300 | /** 301 | * Get tree menu. 302 | * 303 | * @param bool $trans 304 | * 305 | * @return array 306 | */ 307 | public function menu($trans = true) 308 | { 309 | return $this->logs()->menu($trans); 310 | } 311 | 312 | /* ----------------------------------------------------------------- 313 | | Check Methods 314 | | ----------------------------------------------------------------- 315 | */ 316 | 317 | /** 318 | * Determine if the log folder is empty or not. 319 | * 320 | * @return bool 321 | */ 322 | public function isEmpty() 323 | { 324 | return $this->logs()->isEmpty(); 325 | } 326 | } 327 | -------------------------------------------------------------------------------- /src/Utilities/Filesystem.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class Filesystem implements FilesystemContract 19 | { 20 | /* ----------------------------------------------------------------- 21 | | Properties 22 | | ----------------------------------------------------------------- 23 | */ 24 | 25 | /** 26 | * The filesystem instance. 27 | * 28 | * @var \Illuminate\Filesystem\Filesystem 29 | */ 30 | protected $filesystem; 31 | 32 | /** 33 | * The base storage path. 34 | * 35 | * @var string 36 | */ 37 | protected $storagePath; 38 | 39 | /** 40 | * The log files prefix pattern. 41 | * 42 | * @var string 43 | */ 44 | protected $prefixPattern; 45 | 46 | /** 47 | * The log files date pattern. 48 | * 49 | * @var string 50 | */ 51 | protected $datePattern; 52 | 53 | /** 54 | * The log files extension. 55 | * 56 | * @var string 57 | */ 58 | protected $extension; 59 | 60 | /* ----------------------------------------------------------------- 61 | | Constructor 62 | | ----------------------------------------------------------------- 63 | */ 64 | 65 | /** 66 | * Filesystem constructor. 67 | * 68 | * @param \Illuminate\Filesystem\Filesystem $files 69 | * @param string $storagePath 70 | */ 71 | public function __construct(IlluminateFilesystem $files, $storagePath) 72 | { 73 | $this->filesystem = $files; 74 | $this->setPath($storagePath); 75 | $this->setPattern(); 76 | } 77 | 78 | /* ----------------------------------------------------------------- 79 | | Getters & Setters 80 | | ----------------------------------------------------------------- 81 | */ 82 | 83 | /** 84 | * Get the files instance. 85 | * 86 | * @return \Illuminate\Filesystem\Filesystem 87 | */ 88 | public function getInstance() 89 | { 90 | return $this->filesystem; 91 | } 92 | 93 | /** 94 | * Set the log storage path. 95 | * 96 | * @param string $storagePath 97 | * 98 | * @return $this 99 | */ 100 | public function setPath($storagePath) 101 | { 102 | $this->storagePath = $storagePath; 103 | 104 | return $this; 105 | } 106 | 107 | /** 108 | * Get the log pattern. 109 | * 110 | * @return string 111 | */ 112 | public function getPattern(): string 113 | { 114 | return $this->prefixPattern.$this->datePattern.$this->extension; 115 | } 116 | 117 | /** 118 | * Set the log pattern. 119 | * 120 | * @param string $date 121 | * @param string $prefix 122 | * @param string $extension 123 | * 124 | * @return $this 125 | */ 126 | public function setPattern( 127 | $prefix = self::PATTERN_PREFIX, 128 | $date = self::PATTERN_DATE, 129 | $extension = self::PATTERN_EXTENSION 130 | ) { 131 | $this->setPrefixPattern($prefix); 132 | $this->setDatePattern($date); 133 | $this->setExtension($extension); 134 | 135 | return $this; 136 | } 137 | 138 | /** 139 | * Set the log date pattern. 140 | * 141 | * @param string $datePattern 142 | * 143 | * @return $this 144 | */ 145 | public function setDatePattern($datePattern) 146 | { 147 | $this->datePattern = $datePattern; 148 | 149 | return $this; 150 | } 151 | 152 | /** 153 | * Set the log prefix pattern. 154 | * 155 | * @param string $prefixPattern 156 | * 157 | * @return $this 158 | */ 159 | public function setPrefixPattern($prefixPattern) 160 | { 161 | $this->prefixPattern = $prefixPattern; 162 | 163 | return $this; 164 | } 165 | 166 | /** 167 | * Set the log extension. 168 | * 169 | * @param string $extension 170 | * 171 | * @return $this 172 | */ 173 | public function setExtension($extension) 174 | { 175 | $this->extension = $extension; 176 | 177 | return $this; 178 | } 179 | 180 | /* ----------------------------------------------------------------- 181 | | Main Methods 182 | | ----------------------------------------------------------------- 183 | */ 184 | 185 | /** 186 | * Get all log files. 187 | * 188 | * @return array 189 | */ 190 | public function all() 191 | { 192 | return $this->getFiles('*'.$this->extension); 193 | } 194 | 195 | /** 196 | * Get all valid log files. 197 | * 198 | * @return array 199 | */ 200 | public function logs() 201 | { 202 | return $this->getFiles($this->getPattern()); 203 | } 204 | 205 | /** 206 | * List the log files (Only dates). 207 | * 208 | * @param bool $withPaths 209 | * 210 | * @return array 211 | */ 212 | public function dates($withPaths = false) 213 | { 214 | $files = array_reverse($this->logs()); 215 | $dates = $this->extractDates($files); 216 | 217 | if ($withPaths) { 218 | $dates = array_combine($dates, $files); // [date => file] 219 | } 220 | 221 | return $dates; 222 | } 223 | 224 | /** 225 | * Read the log. 226 | * 227 | * @param string $date 228 | * 229 | * @return string 230 | * 231 | * @throws \Arcanedev\LogViewer\Exceptions\FilesystemException 232 | */ 233 | public function read($date) 234 | { 235 | try { 236 | $log = $this->filesystem->get( 237 | $this->getLogPath($date) 238 | ); 239 | } 240 | catch (Exception $e) { 241 | throw new FilesystemException($e->getMessage()); 242 | } 243 | 244 | return $log; 245 | } 246 | 247 | /** 248 | * Delete the log. 249 | * 250 | * @param string $date 251 | * 252 | * @return bool 253 | * 254 | * @throws \Arcanedev\LogViewer\Exceptions\FilesystemException 255 | */ 256 | public function delete(string $date) 257 | { 258 | $path = $this->getLogPath($date); 259 | 260 | throw_unless($this->filesystem->delete($path), FilesystemException::cannotDeleteLog()); 261 | 262 | return true; 263 | } 264 | 265 | /** 266 | * Clear the log files. 267 | * 268 | * @return bool 269 | */ 270 | public function clear() 271 | { 272 | return $this->filesystem->delete($this->logs()); 273 | } 274 | 275 | /** 276 | * Get the log file path. 277 | * 278 | * @param string $date 279 | * 280 | * @return string 281 | */ 282 | public function path($date) 283 | { 284 | return $this->getLogPath($date); 285 | } 286 | 287 | /* ----------------------------------------------------------------- 288 | | Other Methods 289 | | ----------------------------------------------------------------- 290 | */ 291 | 292 | /** 293 | * Get all files. 294 | * 295 | * @param string $pattern 296 | * 297 | * @return array 298 | */ 299 | private function getFiles($pattern) 300 | { 301 | $files = $this->filesystem->glob( 302 | $this->storagePath.DIRECTORY_SEPARATOR.$pattern, defined('GLOB_BRACE') ? GLOB_BRACE : 0 303 | ); 304 | 305 | return array_filter(array_map('realpath', $files)); 306 | } 307 | 308 | /** 309 | * Get the log file path. 310 | * 311 | * @param string $date 312 | * 313 | * @return string 314 | * 315 | * @throws \Arcanedev\LogViewer\Exceptions\FilesystemException 316 | */ 317 | private function getLogPath(string $date) 318 | { 319 | $path = $this->storagePath.DIRECTORY_SEPARATOR.$this->prefixPattern.$date.$this->extension; 320 | 321 | if ( ! $this->filesystem->exists($path)) { 322 | throw FilesystemException::invalidPath($path); 323 | } 324 | 325 | return realpath($path); 326 | } 327 | 328 | /** 329 | * Extract dates from files. 330 | * 331 | * @param array $files 332 | * 333 | * @return array 334 | */ 335 | private function extractDates(array $files) 336 | { 337 | return array_map(function ($file) { 338 | return LogParser::extractDate(basename($file)); 339 | }, $files); 340 | } 341 | } 342 | -------------------------------------------------------------------------------- /src/Utilities/LogChecker.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class LogChecker implements LogCheckerContract 17 | { 18 | /* ----------------------------------------------------------------- 19 | | Properties 20 | | ----------------------------------------------------------------- 21 | */ 22 | 23 | /** 24 | * The config repository instance. 25 | * 26 | * @var \Illuminate\Contracts\Config\Repository 27 | */ 28 | private $config; 29 | 30 | /** 31 | * The filesystem instance. 32 | * 33 | * @var \Arcanedev\LogViewer\Contracts\Utilities\Filesystem 34 | */ 35 | private $filesystem; 36 | 37 | /** 38 | * Log handler mode. 39 | * 40 | * @var string 41 | */ 42 | protected $handler = ''; 43 | 44 | /** 45 | * The check status. 46 | * 47 | * @var bool 48 | */ 49 | private $status = true; 50 | 51 | /** 52 | * The check messages. 53 | * 54 | * @var array 55 | */ 56 | private $messages; 57 | 58 | /** 59 | * Log files statuses. 60 | * 61 | * @var array 62 | */ 63 | private $files = []; 64 | 65 | /* ----------------------------------------------------------------- 66 | | Constructor 67 | | ----------------------------------------------------------------- 68 | */ 69 | 70 | /** 71 | * LogChecker constructor. 72 | * 73 | * @param \Illuminate\Contracts\Config\Repository $config 74 | * @param \Arcanedev\LogViewer\Contracts\Utilities\Filesystem $filesystem 75 | */ 76 | public function __construct(ConfigContract $config, FilesystemContract $filesystem) 77 | { 78 | $this->setConfig($config); 79 | $this->setFilesystem($filesystem); 80 | $this->refresh(); 81 | } 82 | 83 | /* ----------------------------------------------------------------- 84 | | Getters & Setters 85 | | ----------------------------------------------------------------- 86 | */ 87 | 88 | /** 89 | * Set the config instance. 90 | * 91 | * @param \Illuminate\Contracts\Config\Repository $config 92 | * 93 | * @return self 94 | */ 95 | public function setConfig(ConfigContract $config) 96 | { 97 | $this->config = $config; 98 | 99 | return $this; 100 | } 101 | 102 | /** 103 | * Set the Filesystem instance. 104 | * 105 | * @param \Arcanedev\LogViewer\Contracts\Utilities\Filesystem $filesystem 106 | * 107 | * @return self 108 | */ 109 | public function setFilesystem(FilesystemContract $filesystem) 110 | { 111 | $this->filesystem = $filesystem; 112 | 113 | return $this; 114 | } 115 | 116 | /** 117 | * Set the log handler mode. 118 | * 119 | * @param string $handler 120 | * 121 | * @return self 122 | */ 123 | protected function setHandler($handler) 124 | { 125 | $this->handler = strtolower($handler); 126 | 127 | return $this; 128 | } 129 | 130 | /* ----------------------------------------------------------------- 131 | | Main Methods 132 | | ----------------------------------------------------------------- 133 | */ 134 | 135 | /** 136 | * Get messages. 137 | * 138 | * @return array 139 | */ 140 | public function messages() 141 | { 142 | $this->refresh(); 143 | 144 | return $this->messages; 145 | } 146 | 147 | /** 148 | * Check if the checker passes. 149 | * 150 | * @return bool 151 | */ 152 | public function passes() 153 | { 154 | $this->refresh(); 155 | 156 | return $this->status; 157 | } 158 | 159 | /** 160 | * Check if the checker fails. 161 | * 162 | * @return bool 163 | */ 164 | public function fails() 165 | { 166 | return ! $this->passes(); 167 | } 168 | 169 | /** 170 | * Get the requirements. 171 | * 172 | * @return array 173 | */ 174 | public function requirements() 175 | { 176 | $this->refresh(); 177 | 178 | return $this->isDaily() ? [ 179 | 'status' => 'success', 180 | 'header' => 'Application requirements fulfilled.', 181 | 'message' => 'Are you ready to rock ?', 182 | ] : [ 183 | 'status' => 'failed', 184 | 'header' => 'Application requirements failed.', 185 | 'message' => $this->messages['handler'] 186 | ]; 187 | } 188 | 189 | /* ----------------------------------------------------------------- 190 | | Check Methods 191 | | ----------------------------------------------------------------- 192 | */ 193 | 194 | /** 195 | * Is a daily handler mode ? 196 | * 197 | * @return bool 198 | */ 199 | protected function isDaily() 200 | { 201 | return $this->isSameHandler(self::HANDLER_DAILY); 202 | } 203 | 204 | /** 205 | * Is the handler is the same as the application log handler. 206 | * 207 | * @param string $handler 208 | * 209 | * @return bool 210 | */ 211 | private function isSameHandler($handler) 212 | { 213 | return $this->handler === $handler; 214 | } 215 | 216 | /* ----------------------------------------------------------------- 217 | | Other Methods 218 | | ----------------------------------------------------------------- 219 | */ 220 | 221 | /** 222 | * Refresh the checks. 223 | * 224 | * @return \Arcanedev\LogViewer\Utilities\LogChecker 225 | */ 226 | private function refresh() 227 | { 228 | $this->setHandler($this->config->get('logging.default', 'stack')); 229 | 230 | $this->messages = [ 231 | 'handler' => '', 232 | 'files' => [], 233 | ]; 234 | $this->files = []; 235 | 236 | $this->checkHandler(); 237 | $this->checkLogFiles(); 238 | 239 | return $this; 240 | } 241 | 242 | /** 243 | * Check the handler mode. 244 | */ 245 | private function checkHandler() 246 | { 247 | if ($this->isDaily()) return; 248 | 249 | $this->messages['handler'] = 'You should set the log handler to `daily` mode. Please check the LogViewer wiki page (Requirements) for more details.'; 250 | } 251 | 252 | /** 253 | * Check all log files. 254 | */ 255 | private function checkLogFiles() 256 | { 257 | foreach ($this->filesystem->all() as $path) { 258 | $this->checkLogFile($path); 259 | } 260 | } 261 | 262 | /** 263 | * Check a log file. 264 | * 265 | * @param string $path 266 | */ 267 | private function checkLogFile($path) 268 | { 269 | $status = true; 270 | $filename = basename($path); 271 | $message = "The log file [$filename] is valid."; 272 | $pattern = $this->filesystem->getPattern(); 273 | 274 | if ($this->isSingleLogFile($filename)) { 275 | $this->status = $status = false; 276 | $this->messages['files'][$filename] = $message = 277 | "You have a single log file in your application, you should split the [$filename] into separate log files."; 278 | } 279 | elseif ($this->isInvalidLogPattern($filename, $pattern)) { 280 | $this->status = $status = false; 281 | $this->messages['files'][$filename] = $message = 282 | "The log file [$filename] has an invalid date, the format must be like {$pattern}."; 283 | } 284 | 285 | $this->files[$filename] = compact('filename', 'status', 'message', 'path'); 286 | } 287 | 288 | /** 289 | * Check if it's not a single log file. 290 | * 291 | * @param string $file 292 | * 293 | * @return bool 294 | */ 295 | private function isSingleLogFile($file) 296 | { 297 | return $file === 'laravel.log'; 298 | } 299 | 300 | /** 301 | * Check the date of the log file. 302 | * 303 | * @param string $file 304 | * @param string $pattern 305 | * 306 | * @return bool 307 | */ 308 | private function isInvalidLogPattern($file, $pattern) 309 | { 310 | return ((bool) preg_match("/{$pattern}/", $file, $matches)) === false; 311 | } 312 | } 313 | -------------------------------------------------------------------------------- /src/Utilities/LogLevels.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class LogLevels implements LogLevelsContract 19 | { 20 | /* ----------------------------------------------------------------- 21 | | Properties 22 | | ----------------------------------------------------------------- 23 | */ 24 | 25 | /** 26 | * The log levels. 27 | * 28 | * @var array 29 | */ 30 | protected static $levels = []; 31 | 32 | /** 33 | * The Translator instance. 34 | * 35 | * @var \Illuminate\Translation\Translator 36 | */ 37 | private $translator; 38 | 39 | /** 40 | * The selected locale. 41 | * 42 | * @var string 43 | */ 44 | private $locale; 45 | 46 | /* ----------------------------------------------------------------- 47 | | Constructor 48 | | ----------------------------------------------------------------- 49 | */ 50 | 51 | /** 52 | * LogLevels constructor. 53 | * 54 | * @param \Illuminate\Translation\Translator $translator 55 | * @param string $locale 56 | */ 57 | public function __construct(Translator $translator, $locale) 58 | { 59 | $this->setTranslator($translator); 60 | $this->setLocale($locale); 61 | } 62 | 63 | /* ----------------------------------------------------------------- 64 | | Getters & Setters 65 | | ----------------------------------------------------------------- 66 | */ 67 | 68 | /** 69 | * Set the Translator instance. 70 | * 71 | * @param \Illuminate\Translation\Translator $translator 72 | * 73 | * @return $this 74 | */ 75 | public function setTranslator(Translator $translator) 76 | { 77 | $this->translator = $translator; 78 | 79 | return $this; 80 | } 81 | 82 | /** 83 | * Get the selected locale. 84 | * 85 | * @return string 86 | */ 87 | public function getLocale() 88 | { 89 | return $this->locale === 'auto' 90 | ? $this->translator->getLocale() 91 | : $this->locale; 92 | } 93 | 94 | /** 95 | * Set the selected locale. 96 | * 97 | * @param string $locale 98 | * 99 | * @return $this 100 | */ 101 | public function setLocale($locale) 102 | { 103 | $this->locale = is_null($locale) ? 'auto' : $locale; 104 | 105 | return $this; 106 | } 107 | 108 | /* ----------------------------------------------------------------- 109 | | Main Methods 110 | | ----------------------------------------------------------------- 111 | */ 112 | 113 | /** 114 | * Get the log levels. 115 | * 116 | * @param bool $flip 117 | * 118 | * @return array 119 | */ 120 | public function lists($flip = false) 121 | { 122 | return static::all($flip); 123 | } 124 | 125 | /** 126 | * Get translated levels. 127 | * 128 | * @param string|null $locale 129 | * 130 | * @return array 131 | */ 132 | public function names($locale = null) 133 | { 134 | $levels = static::all(true); 135 | 136 | array_walk($levels, function (&$name, $level) use ($locale) { 137 | $name = $this->get($level, $locale); 138 | }); 139 | 140 | return $levels; 141 | } 142 | 143 | /** 144 | * Get PSR log levels. 145 | * 146 | * @param bool $flip 147 | * 148 | * @return array 149 | */ 150 | public static function all($flip = false) 151 | { 152 | if (empty(static::$levels)) { 153 | static::$levels = (new ReflectionClass(LogLevel::class))->getConstants(); 154 | } 155 | 156 | return $flip ? array_flip(static::$levels) : static::$levels; 157 | } 158 | 159 | /** 160 | * Get the translated level. 161 | * 162 | * @param string $key 163 | * @param string|null $locale 164 | * 165 | * @return string 166 | */ 167 | public function get($key, $locale = null) 168 | { 169 | $translations = [ 170 | 'all' => 'All', 171 | LogLevel::EMERGENCY => 'Emergency', 172 | LogLevel::ALERT => 'Alert', 173 | LogLevel::CRITICAL => 'Critical', 174 | LogLevel::ERROR => 'Error', 175 | LogLevel::WARNING => 'Warning', 176 | LogLevel::NOTICE => 'Notice', 177 | LogLevel::INFO => 'Info', 178 | LogLevel::DEBUG => 'Debug', 179 | ]; 180 | 181 | return $this->translator->get(Arr::get($translations, $key, $key), [], $locale ?: $this->getLocale()); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /src/Utilities/LogMenu.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class LogMenu implements LogMenuContract 18 | { 19 | /* ----------------------------------------------------------------- 20 | | Properties 21 | | ----------------------------------------------------------------- 22 | */ 23 | 24 | /** 25 | * The config repository instance. 26 | * 27 | * @var \Illuminate\Contracts\Config\Repository 28 | */ 29 | protected $config; 30 | 31 | /** 32 | * The log styler instance. 33 | * 34 | * @var \Arcanedev\LogViewer\Contracts\Utilities\LogStyler 35 | */ 36 | private $styler; 37 | 38 | /* ----------------------------------------------------------------- 39 | | Constructor 40 | | ----------------------------------------------------------------- 41 | */ 42 | 43 | /** 44 | * LogMenu constructor. 45 | * 46 | * @param \Illuminate\Contracts\Config\Repository $config 47 | * @param \Arcanedev\LogViewer\Contracts\Utilities\LogStyler $styler 48 | */ 49 | public function __construct(ConfigContract $config, LogStylerContract $styler) 50 | { 51 | $this->setConfig($config); 52 | $this->setLogStyler($styler); 53 | } 54 | 55 | /* ----------------------------------------------------------------- 56 | | Getters & Setters 57 | | ----------------------------------------------------------------- 58 | */ 59 | 60 | /** 61 | * Set the config instance. 62 | * 63 | * @param \Illuminate\Contracts\Config\Repository $config 64 | * 65 | * @return self 66 | */ 67 | public function setConfig(ConfigContract $config) 68 | { 69 | $this->config = $config; 70 | 71 | return $this; 72 | } 73 | 74 | /** 75 | * Set the log styler instance. 76 | * 77 | * @param \Arcanedev\LogViewer\Contracts\Utilities\LogStyler $styler 78 | * 79 | * @return self 80 | */ 81 | public function setLogStyler(LogStylerContract $styler) 82 | { 83 | $this->styler = $styler; 84 | 85 | return $this; 86 | } 87 | 88 | /* ----------------------------------------------------------------- 89 | | Main Methods 90 | | ----------------------------------------------------------------- 91 | */ 92 | 93 | /** 94 | * Make log menu. 95 | * 96 | * @param \Arcanedev\LogViewer\Entities\Log $log 97 | * @param bool $trans 98 | * 99 | * @return array 100 | */ 101 | public function make(Log $log, $trans = true) 102 | { 103 | $items = []; 104 | $route = $this->config('menu.filter-route'); 105 | 106 | foreach($log->tree($trans) as $level => $item) { 107 | $items[$level] = array_merge($item, [ 108 | 'url' => route($route, [$log->date, $level]), 109 | 'icon' => $this->isIconsEnabled() ? $this->styler->icon($level)->toHtml() : '', 110 | ]); 111 | } 112 | 113 | return $items; 114 | } 115 | 116 | /* ----------------------------------------------------------------- 117 | | Check Methods 118 | | ----------------------------------------------------------------- 119 | */ 120 | 121 | /** 122 | * Check if the icons are enabled. 123 | * 124 | * @return bool 125 | */ 126 | private function isIconsEnabled() 127 | { 128 | return (bool) $this->config('menu.icons-enabled', false); 129 | } 130 | 131 | /* ----------------------------------------------------------------- 132 | | Other Methods 133 | | ----------------------------------------------------------------- 134 | */ 135 | 136 | /** 137 | * Get config. 138 | * 139 | * @param string $key 140 | * @param mixed $default 141 | * 142 | * @return mixed 143 | */ 144 | private function config($key, $default = null) 145 | { 146 | return $this->config->get("log-viewer.$key", $default); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/Utilities/LogStyler.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class LogStyler implements LogStylerContract 17 | { 18 | /* ----------------------------------------------------------------- 19 | | Properties 20 | | ----------------------------------------------------------------- 21 | */ 22 | 23 | /** 24 | * The config repository instance. 25 | * 26 | * @var \Illuminate\Contracts\Config\Repository 27 | */ 28 | protected $config; 29 | 30 | /* ----------------------------------------------------------------- 31 | | Constructor 32 | | ----------------------------------------------------------------- 33 | */ 34 | 35 | /** 36 | * Create a new instance. 37 | * 38 | * @param \Illuminate\Contracts\Config\Repository $config 39 | */ 40 | public function __construct(ConfigContract $config) 41 | { 42 | $this->config = $config; 43 | } 44 | 45 | /* ----------------------------------------------------------------- 46 | | Getters & Setters 47 | | ----------------------------------------------------------------- 48 | */ 49 | 50 | /** 51 | * Get config. 52 | * 53 | * @param string $key 54 | * @param mixed $default 55 | * 56 | * @return mixed 57 | */ 58 | private function get($key, $default = null) 59 | { 60 | return $this->config->get("log-viewer.$key", $default); 61 | } 62 | 63 | /* ----------------------------------------------------------------- 64 | | Main Methods 65 | | ----------------------------------------------------------------- 66 | */ 67 | 68 | /** 69 | * Make level icon. 70 | * 71 | * @param string $level 72 | * @param string|null $default 73 | * 74 | * @return \Illuminate\Support\HtmlString 75 | */ 76 | public function icon($level, $default = null) 77 | { 78 | return new HtmlString( 79 | '' 80 | ); 81 | } 82 | 83 | /** 84 | * Get level color. 85 | * 86 | * @param string $level 87 | * @param string|null $default 88 | * 89 | * @return string 90 | */ 91 | public function color($level, $default = null) 92 | { 93 | return $this->get("colors.levels.$level", $default); 94 | } 95 | 96 | /** 97 | * Get strings to highlight. 98 | * 99 | * @param array $default 100 | * 101 | * @return array 102 | */ 103 | public function toHighlight(array $default = []) 104 | { 105 | return $this->get('highlight', $default); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /translations/ar.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "تاريخ", 3 | "The list of logs is empty!": "قائمة سجلات فارغة!", 4 | "All": "الجميع", 5 | "Emergency": "حالات الطوارئ", 6 | "Alert": "إنذار", 7 | "Critical": "حرج", 8 | "Error": "خطأ", 9 | "Warning": "تحذير", 10 | "Notice": "ملاحظة", 11 | "Info": "المعلومات", 12 | "Debug": "التصحيح" 13 | } 14 | -------------------------------------------------------------------------------- /translations/bg.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Дата", 3 | "The list of logs is empty!": "Не са намерени логове!", 4 | "All": "Всички", 5 | "Emergency": "Emergency", 6 | "Alert": "Alert", 7 | "Critical": "Critical", 8 | "Error": "Error", 9 | "Warning": "Warning", 10 | "Notice": "Notice", 11 | "Info": "Info", 12 | "Debug": "Debug" 13 | } 14 | -------------------------------------------------------------------------------- /translations/bn.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "তারিখ", 3 | "The list of logs is empty!": "কোন লগ পাওয়া যায়নি!", 4 | "All": "সবগুলি", 5 | "Emergency": "জরুরী", 6 | "Alert": "সতর্ক", 7 | "Critical": "সংকটপূর্ণ", 8 | "Error": "ত্রুটি", 9 | "Warning": "সতর্কতা", 10 | "Notice": "নোটিস", 11 | "Info": "তথ্য", 12 | "Debug": "রুটি অনুসন্ধান" 13 | } 14 | -------------------------------------------------------------------------------- /translations/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Datum", 3 | "The list of logs is empty!": "KeineLogDateiengefunden!", 4 | "All": "Alle", 5 | "Emergency": "Notfall", 6 | "Alert": "Alarm", 7 | "Critical": "Kritisch", 8 | "Error": "Fehler", 9 | "Warning": "Warnung", 10 | "Notice": "Hinweis", 11 | "Info": "Info", 12 | "Debug": "Debug" 13 | } 14 | -------------------------------------------------------------------------------- /translations/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Fecha", 3 | "The list of logs is empty!": "La lista del log está vacía!", 4 | "All": "Todos", 5 | "Emergency": "Emergencia", 6 | "Alert": "Alerta", 7 | "Critical": "Criticos", 8 | "Error": "Errores", 9 | "Warning": "Advertencia", 10 | "Notice": "Aviso", 11 | "Info": "Info", 12 | "Debug": "Debug" 13 | } 14 | -------------------------------------------------------------------------------- /translations/et.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Kuupäev", 3 | "The list of logs is empty!": "Logide nimekiri on tühi!", 4 | "All": "Kõik", 5 | "Emergency": "Erakorraline", 6 | "Alert": "Häire", 7 | "Critical": "Kriitiline", 8 | "Error": "Viga", 9 | "Warning": "Hoiatus", 10 | "Notice": "Teade", 11 | "Info": "Info", 12 | "Debug": "Silumine" 13 | } 14 | -------------------------------------------------------------------------------- /translations/fa.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "تاریخ", 3 | "The list of logs is empty!": "لیست لاگ ها خالی است!", 4 | "All": "همه", 5 | "Emergency": "اورژانسی", 6 | "Alert": "اخطار", 7 | "Critical": "بحرانی", 8 | "Error": "خطا", 9 | "Warning": "هشدار", 10 | "Notice": "اعلان", 11 | "Info": "اطلاعات", 12 | "Debug": "دیباگ" 13 | } 14 | -------------------------------------------------------------------------------- /translations/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Date", 3 | "The list of logs is empty!": "La liste des logs est vide !", 4 | "All": "Tous", 5 | "Emergency": "Urgence", 6 | "Alert": "Alerte", 7 | "Critical": "Critique", 8 | "Error": "Erreur", 9 | "Warning": "Avertissement", 10 | "Notice": "Notice", 11 | "Info": "Info", 12 | "Debug": "Debug" 13 | } 14 | -------------------------------------------------------------------------------- /translations/he.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "תאריך", 3 | "The list of logs is empty!": "רשימת הלוגים ריקה!", 4 | "All": "הכל", 5 | "Emergency": "חרום", 6 | "Alert": "אזעקה", 7 | "Critical": "קריטי", 8 | "Error": "שגיאה", 9 | "Warning": "אזהרה", 10 | "Notice": "הודעה", 11 | "Info": "מידע", 12 | "Debug": "ניפוי" 13 | } 14 | -------------------------------------------------------------------------------- /translations/hu.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Dátum", 3 | "The list of logs is empty!": "A naplók listája üres!", 4 | "All": "Összes", 5 | "Emergency": "Vészhelyzet", 6 | "Alert": "Riasztás", 7 | "Critical": "Kritikus", 8 | "Error": "Hiba", 9 | "Warning": "Figyelmeztetés", 10 | "Notice": "Értesítés", 11 | "Info": "Információ", 12 | "Debug": "Hibakeresés" 13 | } 14 | -------------------------------------------------------------------------------- /translations/hy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Ամսաթիվ", 3 | "The list of logs is empty!": "Լոգերի ցուցակը դատարկ է։", 4 | "All": "Բոլորը", 5 | "Emergency": "Վթարային", 6 | "Alert": "Նախազգուշացում", 7 | "Critical": "Կրիտիկական", 8 | "Error": "Սխալ", 9 | "Warning": "Նախազգուշացում", 10 | "Notice": "Ծանուցում", 11 | "Info": "Տեղեկատվություն", 12 | "Debug": "Կարգաբերում" 13 | } 14 | -------------------------------------------------------------------------------- /translations/id.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Tanggal", 3 | "The list of logs is empty!": "Daftar Log Kosong", 4 | "All": "Semua", 5 | "Emergency": "Darurat", 6 | "Alert": "Waspada", 7 | "Critical": "Kritis", 8 | "Error": "Kesalahan", 9 | "Warning": "Peringatan", 10 | "Notice": "Pemberitahuan", 11 | "Info": "Info", 12 | "Debug": "Debug" 13 | } 14 | -------------------------------------------------------------------------------- /translations/it.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Data", 3 | "The list of logs is empty!": "L'elenco dei log è vuoto!", 4 | "All": "Tutti", 5 | "Emergency": "Emergenza", 6 | "Alert": "Allarme", 7 | "Critical": "Critico", 8 | "Error": "Errore", 9 | "Warning": "Avviso", 10 | "Notice": "Notifica", 11 | "Info": "Info", 12 | "Debug": "Debug" 13 | } 14 | -------------------------------------------------------------------------------- /translations/ja.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "日付", 3 | "The list of logs is empty!": "ログリストが空です!", 4 | "All": "すべて", 5 | "Emergency": "緊急", 6 | "Alert": "警戒", 7 | "Critical": "致命的", 8 | "Error": "エラー", 9 | "Warning": "警告", 10 | "Notice": "通知", 11 | "Info": "情報", 12 | "Debug": "デバッグ" 13 | } 14 | -------------------------------------------------------------------------------- /translations/ko.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "날짜", 3 | "The list of logs is empty!": "로그가 없습니다.", 4 | "All": "전체", 5 | "Emergency": "긴급", 6 | "Alert": "경고", 7 | "Critical": "심각", 8 | "Error": "오류", 9 | "Warning": "주의", 10 | "Notice": "알림", 11 | "Info": "정보", 12 | "Debug": "디버그" 13 | } 14 | -------------------------------------------------------------------------------- /translations/ms.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Tarikh", 3 | "The list of logs is empty!": "Senarai log kosong!", 4 | "All": "Semua", 5 | "Emergency": "Kecemasan", 6 | "Alert": "Waspada", 7 | "Critical": "Kritikal", 8 | "Error": "Ralat", 9 | "Warning": "Amaran", 10 | "Notice": "Notis", 11 | "Info": "Info", 12 | "Debug": "Debug" 13 | } 14 | -------------------------------------------------------------------------------- /translations/nl.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Datum", 3 | "The list of logs is empty!": "De lijst met logs is leeg!", 4 | "All": "Alle", 5 | "Emergency": "Noodgeval", 6 | "Alert": "Alarm", 7 | "Critical": "Cruciaal", 8 | "Error": "Error", 9 | "Warning": "Waarschuwing", 10 | "Notice": "Opmerking", 11 | "Info": "Informatie", 12 | "Debug": "Debug" 13 | } 14 | -------------------------------------------------------------------------------- /translations/pl.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Data", 3 | "The list of logs is empty!": "Lista logów jest pusta!", 4 | "All": "Wszystkie", 5 | "Emergency": "Awaryjne", 6 | "Alert": "Alerty", 7 | "Critical": "Krytyczne", 8 | "Error": "Błędy", 9 | "Warning": "Ostrzeżenia", 10 | "Notice": "Warte uwagi", 11 | "Info": "Informacje", 12 | "Debug": "Debug" 13 | } 14 | -------------------------------------------------------------------------------- /translations/pt-BR.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Data", 3 | "The list of logs is empty!": "A lista de logs está vazia!", 4 | "All": "Todos", 5 | "Emergency": "Emergência", 6 | "Alert": "Alerta", 7 | "Critical": "Crítico", 8 | "Error": "Erro", 9 | "Warning": "Aviso", 10 | "Notice": "Notícia", 11 | "Info": "Informação", 12 | "Debug": "Debug" 13 | } 14 | -------------------------------------------------------------------------------- /translations/ro.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Dată", 3 | "The list of logs is empty!": "Nu există niciun log!", 4 | "All": "Toate", 5 | "Emergency": "Urgență", 6 | "Alert": "Alertă", 7 | "Critical": "Critic", 8 | "Error": "Eroare", 9 | "Warning": "Pericol", 10 | "Notice": "Avertisment", 11 | "Info": "Informare", 12 | "Debug": "Depanare" 13 | } 14 | -------------------------------------------------------------------------------- /translations/ru.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Дата", 3 | "The list of logs is empty!": "Список журналов пуст!", 4 | "All": "Все", 5 | "Emergency": "Аварийная", 6 | "Alert": "Предупреждение", 7 | "Critical": "Критический", 8 | "Error": "Ошибка", 9 | "Warning": "Предупреждение", 10 | "Notice": "Уведомление", 11 | "Info": "Информация", 12 | "Debug": "Отладка" 13 | } 14 | -------------------------------------------------------------------------------- /translations/si.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "දිනය", 3 | "The list of logs is empty!": "සටහන් ලැයිස්තුව හිස්ය", 4 | "All": "සියල්ල", 5 | "Emergency": "හදිසි", 6 | "Alert": "පරීක්ෂාකාරී", 7 | "Critical": "අවදානම්", 8 | "Error": "දෝෂය", 9 | "Warning": "අවවාදය", 10 | "Notice": "නිවේදනය", 11 | "Info": "තොරතුරු", 12 | "Debug": "නිදොස්කරණය" 13 | } 14 | -------------------------------------------------------------------------------- /translations/sv.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Datum", 3 | "The list of logs is empty!": "Det finns inga loggar att visa.", 4 | "All": "Alla", 5 | "Emergency": "Akut", 6 | "Alert": "Alarmerande", 7 | "Critical": "Kritisk", 8 | "Error": "Error", 9 | "Warning": "Varning", 10 | "Notice": "Notis", 11 | "Info": "Information", 12 | "Debug": "Debug" 13 | } 14 | -------------------------------------------------------------------------------- /translations/th.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "วันที่", 3 | "The list of logs is empty!": "ไม่มีรายการล็อก!", 4 | "All": "ทั้งหมด", 5 | "Emergency": "ฉุกเฉิน", 6 | "Alert": "วิกฤติ", 7 | "Critical": "ร้ายแรง", 8 | "Error": "ข้อผิดพลาด", 9 | "Warning": "คำเตือน", 10 | "Notice": "ประกาศ", 11 | "Info": "ข้อมูล", 12 | "Debug": "ดีบัก" 13 | } 14 | -------------------------------------------------------------------------------- /translations/tr.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Tarih", 3 | "The list of logs is empty!": "Günlük listesi boş!", 4 | "All": "Tümü", 5 | "Emergency": "Acil", 6 | "Alert": "Alarm", 7 | "Critical": "Kritik", 8 | "Error": "Hata", 9 | "Warning": "Uyarı", 10 | "Notice": "Bildirim", 11 | "Info": "Bilgi", 12 | "Debug": "Hata ayıklama" 13 | } 14 | -------------------------------------------------------------------------------- /translations/uk.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Дата", 3 | "The list of logs is empty!": "Список журналів порожній!", 4 | "All": "Всі", 5 | "Emergency": "Аварійна", 6 | "Alert": "Попередження", 7 | "Critical": "Критична", 8 | "Error": "Помилка", 9 | "Warning": "Попереждення", 10 | "Notice": "Сповіщення", 11 | "Info": "Інформація", 12 | "Debug": "Відладка" 13 | } 14 | -------------------------------------------------------------------------------- /translations/uz.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "Sana", 3 | "The list of logs is empty!": "Loglar ro'yhati bo'sh!", 4 | "All": "Hammasi", 5 | "Emergency": "Favqulodda holat", 6 | "Alert": "Ogohlantirish", 7 | "Critical": "Xavfli(Muhim)", 8 | "Error": "Xato", 9 | "Warning": "Ogohlantirish", 10 | "Notice": "Eslatma", 11 | "Info": "Ma'lumot", 12 | "Debug": "Debug" 13 | } 14 | -------------------------------------------------------------------------------- /translations/zh-TW.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "日期", 3 | "The list of logs is empty!": "列表中沒有任何紀錄!", 4 | "All": "全部", 5 | "Emergency": "緊急", 6 | "Alert": "警報", 7 | "Critical": "嚴重", 8 | "Error": "錯誤", 9 | "Warning": "警告", 10 | "Notice": "注意", 11 | "Info": "訊息", 12 | "Debug": "除錯" 13 | } 14 | -------------------------------------------------------------------------------- /translations/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "Date": "日期", 3 | "The list of logs is empty!": "日志列表为空!", 4 | "All": "全部", 5 | "Emergency": "危急", 6 | "Alert": "紧急", 7 | "Critical": "严重", 8 | "Error": "错误", 9 | "Warning": "警告", 10 | "Notice": "注意", 11 | "Info": "信息", 12 | "Debug": "调试" 13 | } 14 | -------------------------------------------------------------------------------- /views/bootstrap-3/dashboard.blade.php: -------------------------------------------------------------------------------- 1 | @extends('log-viewer::bootstrap-3._master') 2 | 3 | @section('content') 4 |

@lang('Dashboard')

5 | 6 |
7 |
8 | 9 |
10 |
11 |
12 |
13 | @foreach($percents as $level => $item) 14 |
15 |
16 | 17 | {{ log_styler()->icon($level) }} 18 | 19 | 20 |
21 | {{ $item['name'] }} 22 | 23 | {{ $item['count'] }} @lang('entries') - {!! $item['percent'] !!} % 24 | 25 |
26 |
27 |
28 |
29 |
30 |
31 | @endforeach 32 |
33 |
34 |
35 |
36 | @endsection 37 | 38 | @section('scripts') 39 | 52 | @endsection 53 | -------------------------------------------------------------------------------- /views/bootstrap-3/logs.blade.php: -------------------------------------------------------------------------------- 1 | @extends('log-viewer::bootstrap-3._master') 2 | 3 | 4 | 5 | @section('content') 6 |

@lang('Logs')

7 | 8 | {{ $rows->render() }} 9 | 10 |
11 | 12 | 13 | 14 | @foreach($headers as $key => $header) 15 | 24 | @endforeach 25 | 26 | 27 | 28 | 29 | @forelse($rows as $date => $row) 30 | 31 | @foreach($row as $key => $value) 32 | 43 | @endforeach 44 | 55 | 56 | @empty 57 | 58 | 61 | 62 | @endforelse 63 | 64 |
16 | @if ($key == 'date') 17 | {{ $header }} 18 | @else 19 | 20 | {{ log_styler()->icon($key) }} {{ $header }} 21 | 22 | @endif 23 | @lang('Actions')
33 | @if ($key == 'date') 34 | {{ $value }} 35 | @elseif ($value == 0) 36 | {{ $value }} 37 | @else 38 | 39 | {{ $value }} 40 | 41 | @endif 42 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |
59 | {{ trans('log-viewer::general.empty-logs') }} 60 |
65 |
66 | 67 | {{ $rows->render() }} 68 | @endsection 69 | 70 | @section('modals') 71 | {{-- DELETE MODAL --}} 72 | 96 | @endsection 97 | 98 | @section('scripts') 99 | 152 | @endsection 153 | -------------------------------------------------------------------------------- /views/bootstrap-4/_master.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | LogViewer - Created by ARCANEDEV 9 | {{-- Styles --}} 10 | 11 | 12 | 13 | 218 | 219 | 220 | 242 | 243 |
244 |
245 | @yield('content') 246 |
247 |
248 | 249 | {{-- Footer --}} 250 | 260 | 261 | {{-- Scripts --}} 262 | 263 | 264 | 265 | 266 | 267 | @yield('modals') 268 | @yield('scripts') 269 | 270 | 271 | -------------------------------------------------------------------------------- /views/bootstrap-4/dashboard.blade.php: -------------------------------------------------------------------------------- 1 | @extends('log-viewer::bootstrap-4._master') 2 | 3 | @section('content') 4 | 7 | 8 |
9 |
10 | 11 |
12 | 13 |
14 |
15 | @foreach($percents as $level => $item) 16 |
17 |
18 |
19 | {!! log_styler()->icon($level) !!} 20 |
21 | 22 |
23 | {{ $item['name'] }} 24 | 25 | {{ $item['count'] }} @lang('entries') - {!! $item['percent'] !!} % 26 | 27 |
28 |
29 |
30 |
31 |
32 |
33 | @endforeach 34 |
35 |
36 |
37 | @endsection 38 | 39 | @section('scripts') 40 | 53 | @endsection 54 | -------------------------------------------------------------------------------- /views/bootstrap-4/logs.blade.php: -------------------------------------------------------------------------------- 1 | @extends('log-viewer::bootstrap-4._master') 2 | 3 | 4 | 5 | @section('content') 6 | 9 | 10 |
11 | 12 | 13 | 14 | @foreach($headers as $key => $header) 15 | 24 | @endforeach 25 | 26 | 27 | 28 | 29 | @forelse($rows as $date => $row) 30 | 31 | @foreach($row as $key => $value) 32 | 43 | @endforeach 44 | 55 | 56 | @empty 57 | 58 | 61 | 62 | @endforelse 63 | 64 |
16 | @if ($key == 'date') 17 | {{ $header }} 18 | @else 19 | 20 | {{ log_styler()->icon($key) }} {{ $header }} 21 | 22 | @endif 23 | @lang('Actions')
33 | @if ($key == 'date') 34 | {{ $value }} 35 | @elseif ($value == 0) 36 | {{ $value }} 37 | @else 38 | 39 | {{ $value }} 40 | 41 | @endif 42 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |
59 | @lang('The list of logs is empty!') 60 |
65 |
66 | 67 | {{ $rows->render() }} 68 | @endsection 69 | 70 | @section('modals') 71 | {{-- DELETE MODAL --}} 72 | 96 | @endsection 97 | 98 | @section('scripts') 99 | 152 | @endsection 153 | -------------------------------------------------------------------------------- /views/bootstrap-5/_master.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | LogViewer - Created by ARCANEDEV 9 | {{-- Styles --}} 10 | 11 | 12 | 13 | 218 | 219 | 220 | 242 | 243 |
244 |
245 | @yield('content') 246 |
247 |
248 | 249 | {{-- Footer --}} 250 | 260 | 261 | {{-- Scripts --}} 262 | 263 | 264 | 273 | 274 | @yield('modals') 275 | @yield('scripts') 276 | 277 | 278 | -------------------------------------------------------------------------------- /views/bootstrap-5/dashboard.blade.php: -------------------------------------------------------------------------------- 1 | @extends('log-viewer::bootstrap-5._master') 2 | 3 | @section('content') 4 | 7 | 8 |
9 |
10 | 11 |
12 | 13 |
14 |
15 | @foreach($percents as $level => $item) 16 |
17 |
18 |
19 | {!! log_styler()->icon($level) !!} 20 |
21 | 22 |
23 | {{ $item['name'] }} 24 | 25 | {{ $item['count'] }} @lang('entries') - {!! $item['percent'] !!} % 26 | 27 |
28 |
29 |
30 |
31 |
32 |
33 | @endforeach 34 |
35 |
36 |
37 | @endsection 38 | 39 | @section('scripts') 40 | 53 | @endsection 54 | -------------------------------------------------------------------------------- /views/bootstrap-5/logs.blade.php: -------------------------------------------------------------------------------- 1 | @extends('log-viewer::bootstrap-5._master') 2 | 3 | 4 | 5 | @section('content') 6 | 9 | 10 |
11 | 12 | 13 | 14 | @foreach($headers as $key => $header) 15 | 24 | @endforeach 25 | 26 | 27 | 28 | 29 | @forelse($rows as $date => $row) 30 | 31 | @foreach($row as $key => $value) 32 | 43 | @endforeach 44 | 55 | 56 | @empty 57 | 58 | 61 | 62 | @endforelse 63 | 64 |
16 | @if ($key == 'date') 17 | {{ $header }} 18 | @else 19 | 20 | {{ log_styler()->icon($key) }} {{ $header }} 21 | 22 | @endif 23 | @lang('Actions')
33 | @if ($key == 'date') 34 | {{ $value }} 35 | @elseif ($value == 0) 36 | {{ $value }} 37 | @else 38 | 39 | {{ $value }} 40 | 41 | @endif 42 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |
59 | @lang('The list of logs is empty!') 60 |
65 |
66 | 67 | {{ $rows->render() }} 68 | @endsection 69 | 70 | @section('modals') 71 | {{-- DELETE MODAL --}} 72 | 94 | @endsection 95 | 96 | @section('scripts') 97 | 157 | @endsection 158 | --------------------------------------------------------------------------------