├── .github └── workflows │ └── php.yml ├── .gitignore ├── README.md ├── composer.json ├── composer.lock ├── phpcs.xml ├── phpstan.neon ├── public └── .gitignore └── src ├── Breadcrumbs.php ├── Config.php ├── EventHandler.php ├── Helpers ├── LogLevel.php ├── Uuid.php └── global │ └── breadcrumbs_functions.php ├── MonoProcessors.php ├── Processors ├── BreadcrumbsProcessor.php ├── GitInfoProcessor.php ├── MemoryProcessor.php ├── PhpInfoProcessor.php ├── RequestProcessor.php └── UuidProcessor.php ├── ServiceProvider.php └── config └── mono-processor.php /.github/workflows/php.yml: -------------------------------------------------------------------------------- 1 | name: PHP Composer 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | 17 | - name: Validate composer.json and composer.lock 18 | run: composer validate 19 | 20 | - name: Cache Composer packages 21 | id: composer-cache 22 | uses: actions/cache@v2 23 | with: 24 | path: vendor 25 | key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} 26 | restore-keys: | 27 | ${{ runner.os }}-php- 28 | 29 | - name: Install dependencies 30 | if: steps.composer-cache.outputs.cache-hit != 'true' 31 | run: composer install --prefer-dist --no-progress --no-suggest 32 | 33 | - name: Run phpstan 34 | run: composer run-script phpstan 35 | 36 | - name: Check codestyle 37 | run: composer run-script phpcs 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | vendor/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## MonoProcessor - Supplement your logging with auxiliary information on error 2 | ![Packagist Version](https://img.shields.io/packagist/v/yzen.dev/mono-processor?color=%23007ec6&style=plastic) 3 | ![Packagist Downloads](https://img.shields.io/packagist/dm/yzen.dev/mono-processor) 4 | ![Packagist Downloads](https://img.shields.io/packagist/dt/yzen.dev/mono-processor) 5 | 6 | This Processor will display in the logs bread crumbs by which you can more quickly and accurately identify the cause of the error. 7 | 8 | ## :scroll: **Installation** 9 | The package can be installed via composer: 10 | ``` 11 | composer require yzen.dev/mono-processor 12 | ``` 13 | To get started, first publish MonoProcessor config and view files into your own project: 14 | ``` 15 | php artisan vendor:publish --provider "MonoProcessor\ServiceProvider" 16 | ``` 17 | 18 | # :scroll: **Version Compatibility** 19 | | Laravel | MonoProcessor | 20 | | ------- | ------------- | 21 | | v8.x | v1.x | 22 | | v7.x | v0.3.x | 23 | 24 | ## :scroll: **Features** 25 | * Extends standard logs 26 | * Collection of SQL requests 27 | * Collection of HTTP requests 28 | * Authorized user information 29 | * Route information 30 | * Git information 31 | * PHP information 32 | * Memory information 33 | 34 | ## :scroll: **Usage** 35 | To use MonoProcessor you need to add the following `tap` to your `logging.php` config: 36 | ```php 37 | 'channels' => [ 38 | 'daily' => [ 39 | 'driver' => 'daily', 40 | 'path' => storage_path('logs/laravel.log'), 41 | 'level' => 'debug', 42 | 'days' => env('LOG_DAYS', 7), 43 | 'tap' => [ 44 | MonoProcessor\MonoProcessors::class 45 | ] 46 | ] 47 | ] 48 | ``` 49 | As a result, you will get approximately the following information after the stack: 50 | ![example](http://ipic.su/img/img7/fs/Bezymyannyj.1601029498.jpg) 51 | 52 | ## :scroll: **Configuration** 53 | 54 | | Processor | Description | 55 | | ----------------- | ------------------------------------------------------------ | 56 | | stacktrace | Stack output when an error occurs | 57 | | memoryPeak | Memory peak at runtime | 58 | | git | Git branch and Git commit SHA | 59 | | phpinfo | php info (version) | 60 | | json_format | Output of additional information in the format JSON_PRETTY_PRINT| 61 | | command | Listen console commands | 62 | | levels | levels (DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY)| 63 | | uuid | Adds a unique identifier | 64 | | ----------------- | ------------------------------------------------------------ | 65 | | request | Logging of the received request | 66 | | request.base_info | add request host,ip,url,method | 67 | | request.header | add request header | 68 | | request.body | add request body | 69 | | ----------------- | ------------------------------------------------------------ | 70 | | breadcrumbs | What breadcrumbs do you need to collect | 71 | | breadcrumbs.auth | auth info | 72 | | breadcrumbs.sql | List of sql queries | 73 | | breadcrumbs.route | route info (name,action) | 74 | 75 | 76 | You can also get all harvested breadcrumbs using the `get_breadcrumbs()` method. 77 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yzen.dev/mono-processor", 3 | "version": "1.1", 4 | "description": "This Processor will display in the logs bread crumbs by which you can more quickly and accurately identify the cause of the error.", 5 | "minimum-stability": "dev", 6 | "prefer-stable": true, 7 | "license": "MIT", 8 | "keywords": [ "laravel", "log", "logger", "tap", "monolog", "processor", "breadcrumbs" ], 9 | "authors": [ 10 | { 11 | "name": "Andey Iatsenko", 12 | "email": "yzen.dev@gmail.com" 13 | } 14 | ], 15 | "config": { 16 | "sort-packages": true 17 | }, 18 | "autoload": { 19 | "psr-4": { 20 | "MonoProcessor\\": "src/" 21 | }, 22 | "files": [ 23 | "src/Helpers/global/breadcrumbs_functions.php" 24 | ] 25 | }, 26 | "autoload-dev": { 27 | "psr-4": { 28 | "Tests\\": "tests/" 29 | } 30 | }, 31 | "require": { 32 | "php": "^7.2 || ^8.0", 33 | "illuminate/log": "^v9.0", 34 | "illuminate/auth": "^v9.0", 35 | "illuminate/queue": "^v9.0", 36 | "illuminate/routing": "^v9.0", 37 | "illuminate/http": "^v9.0", 38 | "illuminate/contracts": "^v9.0", 39 | "illuminate/database": "^v9.0", 40 | "illuminate/console": "^v9.0", 41 | "illuminate/support": "^v9.0", 42 | "monolog/monolog": "2.*" 43 | }, 44 | "require-dev": { 45 | "phpstan/phpstan": "^0.12.37", 46 | "mockery/mockery": "^1.0", 47 | "phpunit/phpunit": "^9.3", 48 | "squizlabs/php_codesniffer": "*" 49 | }, 50 | "support": { 51 | "issues": "https://github.com/yzen-dev/mono-processor/issues", 52 | "source": "https://github.com/yzen-dev/mono-processor" 53 | }, 54 | "extra": { 55 | "laravel": { 56 | "providers": [ 57 | "MonoProcessor\\ServiceProvider" 58 | ] 59 | } 60 | }, 61 | "scripts": { 62 | "phpunit": [ 63 | "./vendor/phpunit/phpunit/phpunit --configuration ./phpunit.xml" 64 | ], 65 | "phpstan": [ 66 | "./vendor/bin/phpstan analyse -c ./phpstan.neon src" 67 | ], 68 | "phpcs": [ 69 | "./vendor/bin/phpcs --standard=./phpcs.xml -n --no-cache" 70 | ] 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Custom ruleset Based on PSR12 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | tests/* 25 | 26 | src/ 27 | -------------------------------------------------------------------------------- /phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | level: 6 3 | ignoreErrors: 4 | - '#Parameter \#2 \$listener of method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+\(\) expects Closure|string, array(\$this(MonoProcessor\\EventHandler), string) given.#' 5 | 6 | -------------------------------------------------------------------------------- /public/.gitignore: -------------------------------------------------------------------------------- 1 | phpcs-junit.xml 2 | -------------------------------------------------------------------------------- /src/Breadcrumbs.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | private $breadcrumbs = []; 18 | 19 | /** 20 | * @var Breadcrumbs|null 21 | */ 22 | private static $instance; 23 | 24 | /** 25 | * Get current instance 26 | * 27 | * @return Breadcrumbs 28 | */ 29 | public static function getInstance(): Breadcrumbs 30 | { 31 | if (static::$instance === null) { 32 | static::$instance = new static(); 33 | } 34 | 35 | return static::$instance; 36 | } 37 | 38 | /** 39 | * Add info in breadcrumbs 40 | * 41 | * @param mixed $data 42 | * @return Breadcrumbs 43 | */ 44 | public function add($data): Breadcrumbs 45 | { 46 | $this->breadcrumbs [] = $data; 47 | return $this; 48 | } 49 | 50 | /** 51 | * Add info for key in breadcrumbs 52 | * 53 | * @param string $key 54 | * @param mixed $value 55 | * @return Breadcrumbs 56 | */ 57 | public function push(string $key, $value): Breadcrumbs 58 | { 59 | $this->breadcrumbs[$key][] = $value; 60 | return $this; 61 | } 62 | 63 | /** 64 | * Get all breadcrumbs 65 | * 66 | * @return array 67 | */ 68 | public function getBreadcrumbs(): array 69 | { 70 | return $this->breadcrumbs; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Config.php: -------------------------------------------------------------------------------- 1 | 28 | */ 29 | protected static $queryEventHandlerMap = [ 30 | 'Illuminate\Database\Events\QueryExecuted' => 'queryExecuted', 31 | ]; 32 | 33 | /** 34 | * Map event handlers to events. 35 | * @var array 36 | */ 37 | protected static $consoleEventHandlerMap = [ 38 | 'Illuminate\Console\Events\CommandStarting' => 'commandStarting', 39 | 'Illuminate\Console\Events\CommandFinished' => 'commandFinished', 40 | ]; 41 | 42 | /** 43 | * Map route handlers to events. 44 | * @var array 45 | */ 46 | protected static $routeEventHandlerMap = [ 47 | 'Illuminate\Routing\Events\RouteMatched' => 'routeMatched', 48 | ]; 49 | 50 | /** 51 | * Map queue event handlers to events. 52 | * @var array 53 | */ 54 | protected static $queueEventHandlerMap = [ 55 | 'Illuminate\Queue\Events\JobProcessing' => 'queueJobProcessing', 56 | 'Illuminate\Queue\Events\JobProcessed' => 'queueJobProcessed', 57 | 'Illuminate\Queue\Events\JobExceptionOccurred' => 'queueJobExceptionOccurred', 58 | 'Illuminate\Queue\Events\WorkerStopping' => 'queueWorkerStopping', 59 | ]; 60 | 61 | /** 62 | * Map authentication event handlers to events. 63 | * @var array 64 | */ 65 | protected static $authEventHandlerMap = [ 66 | 'Illuminate\Auth\Events\Authenticated' => 'authenticated', 67 | ]; 68 | 69 | /** 70 | * The Laravel event dispatcher. 71 | * @var \Illuminate\Contracts\Events\Dispatcher 72 | */ 73 | private $events; 74 | 75 | /** 76 | * EventHandler constructor. 77 | * @param \Illuminate\Contracts\Events\Dispatcher $events 78 | */ 79 | public function __construct(Dispatcher $events) 80 | { 81 | $this->events = $events; 82 | } 83 | 84 | /** 85 | * Attach all event handlers. 86 | */ 87 | public function subscribe(): void 88 | { 89 | if (Config::getByKey('breadcrumbs')['route']) { 90 | $this->subscribeRoute(); 91 | } 92 | 93 | if (Config::getByKey('breadcrumbs')['sql']) { 94 | $this->subscribeQuery(); 95 | } 96 | 97 | if (Config::getByKey('command')) { 98 | $this->subscribeConsole(); 99 | } 100 | 101 | if (Config::getByKey('breadcrumbs')['auth']) { 102 | $this->subscribeAuthEvents(); 103 | } 104 | 105 | if (Config::getByKey('breadcrumbs')['queue']) { 106 | $this->subscribeQueueEvents(); 107 | } 108 | } 109 | 110 | /** 111 | * Attach all authentication event handlers. 112 | */ 113 | public function subscribeAuthEvents(): void 114 | { 115 | foreach (static::$authEventHandlerMap as $eventName => $handler) { 116 | $this->events->listen($eventName, [$this, $handler]); 117 | } 118 | } 119 | 120 | /** 121 | * Attach all event handlers. 122 | */ 123 | public function subscribeQuery(): void 124 | { 125 | foreach (static::$queryEventHandlerMap as $eventName => $handler) { 126 | $this->events->listen($eventName, [$this, $handler]); 127 | } 128 | } 129 | 130 | /** 131 | * Attach all event handlers. 132 | */ 133 | public function subscribeConsole(): void 134 | { 135 | foreach (static::$consoleEventHandlerMap as $eventName => $handler) { 136 | $this->events->listen($eventName, [$this, $handler]); 137 | } 138 | } 139 | 140 | /** 141 | * Attach all event handlers. 142 | */ 143 | public function subscribeRoute(): void 144 | { 145 | foreach (static::$routeEventHandlerMap as $eventName => $handler) { 146 | $this->events->listen($eventName, [$this, $handler]); 147 | } 148 | } 149 | 150 | /** 151 | * Attach all queue event handlers. 152 | */ 153 | public function subscribeQueueEvents(): void 154 | { 155 | foreach (static::$queueEventHandlerMap as $eventName => $handler) { 156 | $this->events->listen($eventName, [$this, $handler]); 157 | } 158 | } 159 | 160 | /** 161 | * Pass through the event and capture any errors. 162 | * @param string $method 163 | * @param array $arguments 164 | */ 165 | public function __call(string $method, array $arguments): void 166 | { 167 | $handlerMethod = $handlerMethod = "{$method}Handler"; 168 | if (!method_exists($this, $handlerMethod)) { 169 | return; 170 | //throw new RuntimeException("Missing event handler: {$handlerMethod}"); 171 | } 172 | 173 | try { 174 | call_user_func_array([$this, $handlerMethod], $arguments); 175 | } catch (Exception $exception) { 176 | // Ignore 177 | } 178 | } 179 | 180 | /** 181 | * Since Laravel 5.2 182 | * @param \Illuminate\Routing\Events\RouteMatched $match 183 | */ 184 | protected function routeMatchedHandler(RouteMatched $match): void 185 | { 186 | $route = $match->route; 187 | $routeName = $route->getName(); 188 | $routeAction = $route->getActionName(); 189 | if (empty($routeName) || $routeName === 'Closure') { 190 | $routeName = $route->uri(); 191 | } 192 | Breadcrumbs::getInstance() 193 | ->push( 194 | 'route', 195 | [ 196 | 'name' => $routeName, 197 | 'action' => $routeAction, 198 | ] 199 | ); 200 | } 201 | 202 | /** 203 | * Since Laravel 5.2 204 | * @param \Illuminate\Database\Events\QueryExecuted $query 205 | */ 206 | protected function queryExecutedHandler(QueryExecuted $query): void 207 | { 208 | if (!Config::getByKey('breadcrumbs')['sql']) { 209 | return; 210 | } 211 | $data = ['connectionName' => $query->connectionName]; 212 | 213 | if ($query->time !== null) { 214 | $data['time'] = $query->time; 215 | } 216 | try { 217 | $data['query'] = vsprintf(str_replace(['?'], ['\'%s\''], $query->sql), $query->bindings); 218 | } catch(\Throwable $exception){ 219 | $data['query'] = $query->sql; 220 | } 221 | 222 | Breadcrumbs::getInstance() 223 | ->push('sql', $data); 224 | } 225 | 226 | /** 227 | * Since Laravel 5.2 228 | * @param \Illuminate\Queue\Events\JobProcessing $event 229 | */ 230 | protected function queueJobProcessingHandler(JobProcessing $event): void 231 | { 232 | if (!Config::getByKey('breadcrumbs')['queue']) { 233 | return; 234 | } 235 | 236 | $job = [ 237 | 'job' => $event->job->getName(), 238 | 'queue' => $event->job->getQueue(), 239 | 'attempts' => $event->job->attempts(), 240 | 'connection' => $event->connectionName, 241 | ]; 242 | 243 | if (method_exists($event->job, 'resolveName')) { 244 | $job['resolved'] = $event->job->resolveName(); 245 | } 246 | 247 | Breadcrumbs::getInstance() 248 | ->push('job', $job); 249 | } 250 | 251 | /** 252 | * @param JobExceptionOccurred $event 253 | */ 254 | protected function queueJobExceptionOccurredHandler(JobExceptionOccurred $event): void 255 | { 256 | if (!Config::getByKey('breadcrumbs')['queue']) { 257 | return; 258 | } 259 | 260 | $job = [ 261 | 'job' => $event->job->getName(), 262 | 'queue' => $event->job->getQueue(), 263 | 'attempts' => $event->job->attempts(), 264 | 'connection' => $event->connectionName, 265 | ]; 266 | 267 | if (method_exists($event->job, 'resolveName')) { 268 | $job['resolved'] = $event->job->resolveName(); 269 | } 270 | 271 | Breadcrumbs::getInstance() 272 | ->push('job', $job); 273 | } 274 | 275 | /** 276 | * Since Laravel 5.2 277 | * @param WorkerStopping $event 278 | */ 279 | protected function queueWorkerStoppingHandler(WorkerStopping $event): void 280 | { 281 | Breadcrumbs::getInstance() 282 | ->push('worker', $event); 283 | } 284 | 285 | /** 286 | * Since Laravel 5.5 287 | * @param \Illuminate\Console\Events\CommandStarting $event 288 | */ 289 | protected function commandStartingHandler(CommandStarting $event): void 290 | { 291 | if ($event->command) { 292 | if (Config::getByKey('command')) { 293 | return; 294 | } 295 | Breadcrumbs::getInstance() 296 | ->push('command', $event); 297 | } 298 | } 299 | 300 | /** 301 | * Since Laravel 5.5 302 | * @param \Illuminate\Console\Events\CommandFinished $event 303 | */ 304 | protected function commandFinishedHandler(CommandFinished $event): void 305 | { 306 | Breadcrumbs::getInstance() 307 | ->push('command', $event); 308 | } 309 | 310 | /** 311 | * Since Laravel 5.3 312 | * @param \Illuminate\Auth\Events\Authenticated $event 313 | */ 314 | protected function authenticatedHandler(Authenticated $event): void 315 | { 316 | Breadcrumbs::getInstance() 317 | ->push( 318 | 'user', 319 | [ 320 | 'id' => optional($event->user)->id, 321 | 'email' => optional($event->user)->email 322 | ] 323 | ); 324 | } 325 | } 326 | -------------------------------------------------------------------------------- /src/Helpers/LogLevel.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | function get_breadcrumbs(): array 10 | { 11 | return \MonoProcessor\Breadcrumbs::getInstance()->getBreadcrumbs(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/MonoProcessors.php: -------------------------------------------------------------------------------- 1 | getHandlers() as $handler) { 30 | $handler->pushProcessor(new GitInfoProcessor()); 31 | $handler->pushProcessor(new MemoryProcessor()); 32 | $handler->pushProcessor(new PhpInfoProcessor()); 33 | $handler->pushProcessor(new BreadcrumbsProcessor()); 34 | $handler->pushProcessor(new UuidProcessor()); 35 | /* @phpstan-ignore-next-line */ 36 | if (!app()->runningInConsole()) { 37 | $handler->pushProcessor(new RequestProcessor()); 38 | } 39 | 40 | $format = new LineFormatter( 41 | "[%datetime%] %channel%.%level_name%: %message%\n%context%\n%extra%", 42 | 'Y-m-d H:i:s', 43 | true, 44 | true 45 | ); 46 | 47 | if (Config::isEnabledValue('json_format')) { 48 | $format->setJsonPrettyPrint(true); 49 | } 50 | if (Config::isEnabledValue('stacktrace')) { 51 | $format->includeStacktraces(true); 52 | } 53 | $handler->setFormatter($format); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Processors/BreadcrumbsProcessor.php: -------------------------------------------------------------------------------- 1 | $record 20 | * @return array 21 | */ 22 | public function __invoke(array $record): array 23 | { 24 | if (!LogLevel::isWrite($record['level_name'])) { 25 | return $record; 26 | } 27 | 28 | $record['extra'] += [ 29 | 'breadcrumbs' => Breadcrumbs::getInstance()->getBreadcrumbs(), 30 | ]; 31 | 32 | return $record; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Processors/GitInfoProcessor.php: -------------------------------------------------------------------------------- 1 | $record 20 | * @return array 21 | */ 22 | public function __invoke(array $record): array 23 | { 24 | if (!LogLevel::isWrite($record['level_name']) || !Config::isEnabledValue('git')) { 25 | return $record; 26 | } 27 | 28 | $branches = shell_exec('git branch -v --no-abbrev'); 29 | 30 | if ($branches !== null && preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)(.*)}m', $branches, $matches)) { 31 | $record['extra']['git'] = [ 32 | 'branch' => $matches[1], 33 | 'commit' => $matches[2], 34 | 'name' => $matches[3], 35 | ]; 36 | } 37 | 38 | return $record; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Processors/MemoryProcessor.php: -------------------------------------------------------------------------------- 1 | $record 19 | * @return array 20 | */ 21 | public function __invoke(array $record): array 22 | { 23 | if (!LogLevel::isWrite($record['level_name']) || !Config::isEnabledValue('memoryPeak')) { 24 | return $record; 25 | } 26 | 27 | $usage = memory_get_peak_usage(true); 28 | $usage = $this->formatBytes($usage); 29 | $record['extra']['memory_peak_usage'] = $usage; 30 | 31 | return $record; 32 | } 33 | 34 | /** 35 | * @param int $bytes 36 | * @return string 37 | */ 38 | public function formatBytes(int $bytes): string 39 | { 40 | $unit = ['b', 'kb', 'mb', 'gb', 'tb', 'pb']; 41 | return @round($bytes / pow(1024, ($i = floor(log($bytes, 1024)))), 2) . ' ' . $unit[$i]; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Processors/PhpInfoProcessor.php: -------------------------------------------------------------------------------- 1 | $record 20 | * @return array 21 | */ 22 | public function __invoke(array $record): array 23 | { 24 | if (!LogLevel::isWrite($record['level_name']) || !Config::isEnabledValue('phpinfo')) { 25 | return $record; 26 | } 27 | $record['extra'] += [ 28 | 'php' => [ 29 | 'version' => PHP_VERSION, 30 | ] 31 | ]; 32 | 33 | return $record; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Processors/RequestProcessor.php: -------------------------------------------------------------------------------- 1 | $record 21 | * @return array 22 | */ 23 | public function __invoke(array $record): array 24 | { 25 | if (!LogLevel::isWrite($record['level_name'])) { 26 | return $record; 27 | } 28 | if ( 29 | !Config::getByKey('request')['base_info'] && 30 | !Config::getByKey('request')['header'] && 31 | !Config::getByKey('request')['body'] 32 | ) { 33 | return $record; 34 | } 35 | 36 | $record['extra']['request'] = []; 37 | 38 | if (Config::getByKey('request')['base_info']) { 39 | $record['extra']['request'] += [ 40 | 'base_info' => [ 41 | 'ip' => $_SERVER['REMOTE_ADDR'], 42 | 'http_method' => $_SERVER['REQUEST_METHOD'], 43 | 'full_url' => $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'], 44 | 'server' => $_SERVER['SERVER_NAME'], 45 | 'url' => $_SERVER['REQUEST_URI'], 46 | ], 47 | ]; 48 | } 49 | 50 | $request = Request::instance(); 51 | if (Config::getByKey('request')['header']) { 52 | $record['extra']['request'] += [ 53 | 'header' => $request->header(), 54 | ]; 55 | } 56 | if (Config::getByKey('request')['body']) { 57 | $record['extra']['request'] += [ 58 | 'body' => $request->all(), 59 | ]; 60 | } 61 | 62 | return $record; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Processors/UuidProcessor.php: -------------------------------------------------------------------------------- 1 | $record 21 | * @return array 22 | */ 23 | public function __invoke(array $record): array 24 | { 25 | if (!LogLevel::isWrite($record['level_name']) || !Config::isEnabledValue('uuid')) { 26 | return $record; 27 | } 28 | $record['extra'] += [ 29 | 'uuid' => Uuid::uuidV4() 30 | ]; 31 | 32 | return $record; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/ServiceProvider.php: -------------------------------------------------------------------------------- 1 | bindEvents(); 26 | 27 | $this->publishes( 28 | [ 29 | /* @phpstan-ignore-next-line */ 30 | __DIR__ . '/config/mono-processor.php' => config_path(static::$package . '.php'), 31 | ], 32 | 'config' 33 | ); 34 | } 35 | 36 | /** 37 | * Register bindings in the container. 38 | * @return void 39 | */ 40 | public function register(): void 41 | { 42 | $this->mergeConfigFrom(__DIR__ . '/config/mono-processor.php', self::$package); 43 | } 44 | 45 | /** 46 | * Bind to the Laravel event dispatcher to log events. 47 | */ 48 | protected function bindEvents(): void 49 | { 50 | /* @phpstan-ignore-next-line */ 51 | $handler = new EventHandler($this->app->events); 52 | 53 | $handler->subscribe(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/config/mono-processor.php: -------------------------------------------------------------------------------- 1 | true, 6 | 7 | // memory peak at runtime 8 | 'memoryPeak' => true, 9 | 10 | // information about the current branch and commit 11 | 'git' => true, 12 | 13 | // php info (version) 14 | 'phpinfo' => true, 15 | 16 | // Output of additional information in the format JSON_PRETTY_PRINT 17 | 'json_format' => true, 18 | 19 | // Listen console commands 20 | 'command' => true, 21 | 22 | // Logging of the received request 23 | 'request' => [ 24 | 'base_info' => true, 25 | 'header' => true, 26 | 'body' => true, 27 | ], 28 | 29 | // What breadcrumbs do you need to collect 30 | 'breadcrumbs' => [ 31 | // auth info 32 | 'auth' => true, 33 | 34 | // List of sql queries 35 | 'sql' => true, 36 | 37 | // route info 38 | 'route' => true, 39 | 40 | // queue info (WIP) 41 | 'queue' => true, 42 | ], 43 | 44 | // Levels for which you want to display 45 | 'levels' => [ 46 | 'ERROR', 47 | 'EMERGENCY' 48 | ] 49 | ]; 50 | --------------------------------------------------------------------------------