Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/dmitry-ivanov/laravel-console-logger
Logging and Notifications for Laravel Console Commands.
https://github.com/dmitry-ivanov/laravel-console-logger
command console email-notifications error-handling guzzle-middleware laravel laravel-package logger notifications
Last synced: 8 days ago
JSON representation
Logging and Notifications for Laravel Console Commands.
- Host: GitHub
- URL: https://github.com/dmitry-ivanov/laravel-console-logger
- Owner: dmitry-ivanov
- License: mit
- Created: 2016-06-14T11:35:10.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2024-03-06T20:20:38.000Z (8 months ago)
- Last Synced: 2024-10-23T10:34:25.887Z (16 days ago)
- Topics: command, console, email-notifications, error-handling, guzzle-middleware, laravel, laravel-package, logger, notifications
- Language: PHP
- Homepage:
- Size: 2.16 MB
- Stars: 87
- Watchers: 6
- Forks: 10
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
![Logging and Notifications for Laravel Console Commands](art/1380x575-optimized.jpg)
# Laravel Console Logger
[](https://buymeacoffee.com/dmitry.ivanov)
[![StyleCI](https://github.styleci.io/repos/61117768/shield?branch=master&style=flat)](https://github.styleci.io/repos/61117768?branch=master)
[![Build Status](https://img.shields.io/github/actions/workflow/status/dmitry-ivanov/laravel-console-logger/tests.yml?branch=master)](https://github.com/dmitry-ivanov/laravel-console-logger/actions?query=workflow%3Atests+branch%3Amaster)
[![Coverage Status](https://img.shields.io/codecov/c/github/dmitry-ivanov/laravel-console-logger/master)](https://app.codecov.io/gh/dmitry-ivanov/laravel-console-logger/tree/master)![Packagist Version](https://img.shields.io/packagist/v/illuminated/console-logger)
![Packagist Stars](https://img.shields.io/packagist/stars/illuminated/console-logger)
![Packagist Downloads](https://img.shields.io/packagist/dt/illuminated/console-logger)
![Packagist License](https://img.shields.io/packagist/l/illuminated/console-logger)Logging and Notifications for Laravel Console Commands.
| Laravel | Console Logger |
|---------|---------------------------------------------------------------------------|
| 11.x | _[Support](https://buymeacoffee.com/dmitry.ivanov)_ ☕ |
| 10.x | [10.x](https://github.com/dmitry-ivanov/laravel-console-logger/tree/10.x) |
| 9.x | [9.x](https://github.com/dmitry-ivanov/laravel-console-logger/tree/9.x) |
| 8.x | [8.x](https://github.com/dmitry-ivanov/laravel-console-logger/tree/8.x) |
| 7.x | [7.x](https://github.com/dmitry-ivanov/laravel-console-logger/tree/7.x) |
| 6.x | [6.x](https://github.com/dmitry-ivanov/laravel-console-logger/tree/6.x) |
| 5.8.* | [5.8.*](https://github.com/dmitry-ivanov/laravel-console-logger/tree/5.8) |
| 5.7.* | [5.7.*](https://github.com/dmitry-ivanov/laravel-console-logger/tree/5.7) |
| 5.6.* | [5.6.*](https://github.com/dmitry-ivanov/laravel-console-logger/tree/5.6) |
| 5.5.* | [5.5.*](https://github.com/dmitry-ivanov/laravel-console-logger/tree/5.5) |
| 5.4.* | [5.4.*](https://github.com/dmitry-ivanov/laravel-console-logger/tree/5.4) |
| 5.3.* | [5.3.*](https://github.com/dmitry-ivanov/laravel-console-logger/tree/5.3) |
| 5.2.* | [5.2.*](https://github.com/dmitry-ivanov/laravel-console-logger/tree/5.2) |
| 5.1.* | [5.1.*](https://github.com/dmitry-ivanov/laravel-console-logger/tree/5.1) |![Laravel Console Logger - Demo](doc/img/demo.gif)
## Table of contents
- [Usage](#usage)
- [Available methods](#available-methods)
- [Channels](#channels)
- [File channel](#file-channel)
- [Notification channels](#notification-channels)
- [Email channel](#email-channel)
- [Database channel](#database-channel)
- [Error handling](#error-handling)
- [Exceptions with context](#exceptions-with-context)
- [Guzzle 6+ integration](#guzzle-6-integration)
- [Powered by Monolog](#powered-by-monolog)
- [Troubleshooting](#troubleshooting)
- [Trait included, but nothing happens?](#trait-included-but-nothing-happens)
- [Several traits conflict?](#several-traits-conflict)
- [Sponsors](#sponsors)
- [License](#license)## Usage
1. Install the package via Composer:
```shell script
composer require illuminated/console-logger
```2. Use `Illuminated\Console\Loggable` trait:
```php
use Illuminated\Console\Loggable;class ExampleCommand extends Command
{
use Loggable;public function handle()
{
$this->logInfo('Hello World!');
}// ...
}
```3. Run the command and check your logs:
```
[2020-05-11 17:19:21]: [INFO]: Command `App\Console\Commands\ExampleCommand` initialized.
[2020-05-11 17:19:21]: [INFO]: Host: `MyHost.local` (`10.0.1.1`).
[2020-05-11 17:19:21]: [INFO]: Database host: `MyHost.local`, port: `3306`, ip: ``.
[2020-05-11 17:19:21]: [INFO]: Database date: `2020-05-11 17:19:21`.
[2020-05-11 17:19:21]: [INFO]: Hello World!
[2020-05-11 17:19:21]: [INFO]: Execution time: 0.009 sec.
[2020-05-11 17:19:21]: [INFO]: Memory peak usage: 8 MB.
```## Available methods
The `Loggable` trait provides these [PSR-3](http://www.php-fig.org/psr/psr-3/) methods:
- `logDebug()`
- `logInfo()`
- `logNotice()`
- `logWarning()`
- `logError()`
- `logCritical()`
- `logAlert()`
- `logEmergency()`Use them in your console commands to log required information.
## Channels
Log messages could be handled in multiple different ways.
It might be writing data into the log file, storing it in the database, sending an email, etc.
### File channel
File channel simply writes log messages into the log file.
Each of the commands would have a separate folder within the `storage/logs` dir.
For example, `foo-bar` command logs would be stored in the `storage/logs/foo-bar` folder.
You can customize the storage folder, and the max number of stored log files by overriding proper methods:
```php
class ExampleCommand extends Command
{
use Loggable;protected function getLogPath()
{
return storage_path('logs/custom-folder/date.log');
}protected function getLogMaxFiles()
{
return 45;
}// ...
}
```## Notification channels
If you want to be notified about errors in your console commands - use notification channels.
Notification channels are optional and disabled by default. Each of them could be enabled and configured as needed.
By default, you'll get notifications with a level higher than NOTICE (see [PSR-3 log levels](https://www.php-fig.org/psr/psr-3/#5-psrlogloglevel)).
It means that you'll get NOTICE, WARNING, ERROR, CRITICAL, ALERT, and EMERGENCY notifications, by default.Of course, you can customize that, as well as other channel-specific details.
### Email channel
The email channel provides notifications via email.
Set the recipients, and email notifications are ready to go!
```php
class ExampleCommand extends Command
{
use Loggable;protected function getEmailNotificationsRecipients()
{
return [
['address' => '[email protected]', 'name' => 'John Doe'],
['address' => '[email protected]', 'name' => 'Jane Smith'],
];
}// ...
}
```There's a bunch of methods related to the email channel.
By overriding those methods, you can change the subject, `from` address, notification level, etc.
Deduplication is another useful feature worth mentioning. Sometimes the same error might occur many times in a row.
For example, you're using an external web service that is down. Or imagine that the database server goes down.
You'll get a lot of similar emails in those cases. Deduplication is the right solution for that.You can enable it and adjust the time in seconds, for which deduplication works:
```php
class ExampleCommand extends Command
{
use Loggable;protected function useEmailNotificationsDeduplication()
{
return true;
}protected function getEmailNotificationsDeduplicationTime()
{
return 90;
}// ...
}
```### Database channel
The database channel provides a way to save notifications in the database.
The easiest way to start using it:
```php
class ExampleCommand extends Command
{
use Loggable;protected function useDatabaseNotifications()
{
return true;
}// ...
}
```Notifications would be stored in the `iclogger_notifications` table, which would be automatically created if it doesn't exist yet.
Of course, you can customize the table name, and even the saving logic, by overriding proper methods:
```php
class ExampleCommand extends Command
{
use Loggable;protected function useDatabaseNotifications()
{
return true;
}protected function getDatabaseNotificationsTable()
{
return 'custom_notifications';
}protected function getDatabaseNotificationsCallback()
{
return function (array $record) {
CustomNotification::create([
'level' => $record['level'],
'level_name' => $record['level_name'],
'message' => $record['message'],
'context' => get_dump($record['context']),
'custom_field' => 'Foo Bar Baz!',
]);
};
}// ...
}
```## Error handling
Another cool feature that is enabled by default - is error handling.
The package automatically logs everything for you:
severe problems - exceptions and fatal errors, and even small things, such as PHP notices and warnings.Add notifications to that, and you'll immediately know when something goes wrong in your console commands!
### Exceptions with context
Sometimes it's useful to pass an additional context of the thrown exception.
Use the `Illuminated\Console\Exceptions\RuntimeException` for that:
```php
use Illuminated\Console\Exceptions\RuntimeException;class ExampleCommand extends Command
{
use Loggable;public function handle()
{
throw new RuntimeException('Whoops! We have a problem!', [
'some' => 123,
'extra' => true,
'context' => null,
]);
}// ...
}
``````
[2020-05-11 17:19:21]: [ERROR]: Whoops! We have a problem!
array:5 [
"code" => 0
"message" => "Whoops! We have a problem!"
"file" => "/Applications/MAMP/htdocs/icl-test/app/Console/Commands/ExampleCommand.php"
"line" => 22
"context" => array:3 [
"some" => 123
"extra" => true
"context" => null
]
]
```## Guzzle 6+ integration
If you're using [Guzzle](https://github.com/guzzle/guzzle), you might want to have a full log of your HTTP interactions.
The `iclogger_guzzle_middleware()` function provides a pre-configured [Guzzle Middleware](https://docs.guzzlephp.org/en/stable/handlers-and-middleware.html) for that:
```php
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;// Create a log middleware
$logMiddleware = iclogger_guzzle_middleware($logger);// Add it to the HandlerStack
$handler = HandlerStack::create();
$handler->push($logMiddleware);// Use the created handler in your Guzzle Client
$client = new Client([
'handler' => $handler,
'base_uri' => 'https://example.com',
]);// Now, all your HTTP requests and responses would be logged automatically!
// $client->get('/foo');
```If you're using JSON, you might want to get auto decoding for your request params and response bodies:
```php
$logMiddleware = iclogger_guzzle_middleware($logger, 'json');
```Also, you can disable logging of specific request params and/or response bodies, based on your custom logic:
```php
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;// Disable logging of request params for the `/foo` endpoint
$shouldLogRequestParams = function (RequestInterface $request) {
return ! str_ends_with($request->getUri(), '/foo');
};// Disable logging of response bodies greater than 100 KB
$shouldLogResponseBody = function (RequestInterface $request, ResponseInterface $response) {
return $response->getHeaderLine('Content-Length') < 102400;
};$logMiddleware = iclogger_guzzle_middleware($logger, 'json', $shouldLogRequestParams, $shouldLogResponseBody);
```## Powered by Monolog
This package uses the powerful [Monolog Logger](https://github.com/Seldaek/monolog).
You can access the underlying instance of Monolog by:
- Using the command's `icLogger()` method:
```php
class ExampleCommand extends Command
{
use Loggable;public function handle()
{
$logger = $this->icLogger();
}// ...
}
```- Or via the Laravel's Service Container:
```php
$logger = app('log.iclogger');
```## Troubleshooting
### Trait included, but nothing happens?
`Loggable` trait overrides the `initialize()` method:
```php
trait Loggable
{
protected function initialize(InputInterface $input, OutputInterface $output)
{
$this->initializeLogging();parent::initialize($input, $output);
}// ...
}
```If your command overrides the `initialize()` method too, you have to call the `initializeLogging()` method by yourself:
```php
class ExampleCommand extends Command
{
use Loggable;protected function initialize(InputInterface $input, OutputInterface $output)
{
// You have to call it first
$this->initializeLogging();// Then goes your custom code
$this->foo = $this->argument('foo');
$this->bar = $this->argument('bar');
$this->baz = $this->argument('baz');
}// ...
}
```### Several traits conflict?
If you're using another `illuminated/console-%` package, you'll get the "traits conflict" error.
For example, if you're building a loggable command, which [doesn't allow overlapping](https://github.com/dmitry-ivanov/laravel-console-mutex):
```php
class ExampleCommand extends Command
{
use Loggable;
use WithoutOverlapping;// ...
}
```You'll get the traits conflict, because both of those traits are overriding the `initialize()` method:
> If two traits insert a method with the same name, a fatal error is produced, if the conflict is not explicitly resolved.To fix that - override the `initialize()` method and resolve the conflict:
```php
class ExampleCommand extends Command
{
use Loggable;
use WithoutOverlapping;protected function initialize(InputInterface $input, OutputInterface $output)
{
// Initialize conflicting traits
$this->initializeMutex();
$this->initializeLogging();
}// ...
}
```## Sponsors
[![Laravel Idea](art/sponsor-laravel-idea.png)](https://laravel-idea.com)
[![Material Theme UI Plugin](art/sponsor-material-theme.png)](https://material-theme.com)## License
Laravel Console Logger is open-sourced software licensed under the [MIT license](LICENSE.md).
[](https://buymeacoffee.com/dmitry.ivanov)