Skip to content

Commit

Permalink
Merge pull request #24 from pagevamp/use-as-custom-driver
Browse files Browse the repository at this point in the history
try as custom driver
  • Loading branch information
developernaren authored Jul 29, 2021
2 parents 6081bbc + 7841ade commit b7a65ba
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 96 deletions.
7 changes: 0 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,6 @@
"maxbanton/cwh": "^1.1.14 || ^2.0",
"illuminate/support": "^5.1 || ^6.0 || ^7.0 || ^8.0"
},
"extra": {
"laravel": {
"providers": [
"Pagevamp\\Providers\\CloudWatchServiceProvider"
]
}
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.12 || ^2.16",
"phpunit/phpunit": "^6.5 || ^8.4 || ^9.0",
Expand Down
4 changes: 3 additions & 1 deletion config/logging.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

return [
'cloudwatch' => [
'driver' => 'custom',
'name' => env('CLOUDWATCH_LOG_NAME', ''),
'region' => env('CLOUDWATCH_LOG_REGION', ''),
'credentials' => [
Expand All @@ -12,7 +13,7 @@
'retention' => env('CLOUDWATCH_LOG_RETENTION_DAYS', 14),
'group_name' => env('CLOUDWATCH_LOG_GROUP_NAME', 'laravel_app'),
'version' => env('CLOUDWATCH_LOG_VERSION', 'latest'),
'disabled' => env('DISABLE_CLOUDWATCH_LOG', false),
'batch_size' => env('CLOUDWATCH_LOG_BATCH_SIZE', 10000),
'formatter' => function ($configs) {
return new \Monolog\Formatter\LineFormatter(
'%channel%: %level_name%: %message% %context% %extra%',
Expand All @@ -21,5 +22,6 @@
true
);
},
'via' => \Pagevamp\Logger::class
],
];
32 changes: 11 additions & 21 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
## Logger for Aws Cloud Watch

### Breaking Change for version 1.0

When this package started it started as a listener for log event and would only work with another channel.
This package would listen to log events and just add extra log to cloud watch. So you did not need to add mention this as `channel`.
But after `1.0` it works as a custom driver.
So, you MUST add a `LOG_CHANNEL` as `cloudwatch` for logging in your config for this to work going forward

### Installation

`composer require pagevamp/laravel-cloudwatch-logs`
Expand Down Expand Up @@ -28,34 +35,17 @@ Config for logging is defined at `config/logging.php`. Add `cloudwatch` to the `
'retention' => env('CLOUDWATCH_LOG_RETENTION_DAYS', 14),
'group_name' => env('CLOUDWATCH_LOG_GROUP_NAME', 'laravel_app'),
'version' => env('CLOUDWATCH_LOG_VERSION', 'latest'),
'formatter' => \Monolog\Formatter\JsonFormatter::class,
'disabled' => env('DISABLE_CLOUDWATCH_LOG', false),
'formatter' => \Monolog\Formatter\JsonFormatter::class,
'batch_size' => env('CLOUDWATCH_LOG_BATCH_SIZE', 10000),
'via' => \Pagevamp\Logger::class,
],
]
```

Add correct values to keys in your `.env` file. And it should work.
And set the `LOG_CHANNEL` in your environment variable to `cloudwatch`.

If the role of your AWS EC2 instance has access to Cloudwatch logs, `CLOUDWATCH_LOG_KEY` and `CLOUDWATCH_LOG_SECRET` need not be defined in your `.env` file.

### Add To Project

#### Laravel 5.5 or Higher

This package uses laravel's [Package discovery](https://laravel.com/docs/5.6/packages#package-discovery). To disable this package by default you can add `DISABLE_CLOUDWATCH_LOG=true` to you local `.env` file and this package will be disabled.

#### Laravel 5.4 or Lower

Add to the `providers` array in `config/app.php`:

```
Pagevamp\Providers\CloudWatchServiceProvider::class
```

### Concept

This package relies on laravel's listener for log events. This package DOES NOT replace the default logging, instead adds additional log to AWS CLoud Watch. Hence you do not have to change the default log driver to make this work.

### Contribution

I have added a `pre-commit` hook to run `php-cs-fixer` whenever you make a commit. To enable this run `sh hooks.sh`.
Expand Down
69 changes: 16 additions & 53 deletions src/Providers/CloudWatchServiceProvider.php → src/Logger.php
Original file line number Diff line number Diff line change
@@ -1,58 +1,38 @@
<?php

namespace Pagevamp\Providers;
namespace Pagevamp;

use Aws\CloudWatchLogs\CloudWatchLogsClient;
use Illuminate\Support\ServiceProvider;
use Maxbanton\Cwh\Handler\CloudWatch;
use Monolog\Formatter\LineFormatter;
use Monolog\Logger;
use Pagevamp\Exceptions\IncompleteCloudWatchConfig;

class CloudWatchServiceProvider extends ServiceProvider
class Logger
{
public function boot()

private $app;

public function __construct($app = null)
{
$isCloudWatchDisabled = $this->app->make('config')->get('logging.channels.cloudwatch.disabled');
if (!$isCloudWatchDisabled) {
$app = $this->app;
$app['log']->listen(function () use ($app) {
$args = \func_get_args();

// Laravel 5.4 returns a MessageLogged instance only
if (1 == \count($args)) {
$level = $args[0]->level;
$message = $args[0]->message;
$context = $args[0]->context;
} else {
$level = $args[0];
$message = $args[1];
$context = $args[2];
}

if ($message instanceof \ErrorException) {
return $this->getLogger()->log($level, $message, $context);
}

if ($app['cloudwatch.logger'] instanceof Logger) {
$app['cloudwatch.logger']->log($level, $message, $context);
}
});
}
$this->app = $app;
}

public function getLogger()
public function __invoke(array $config)
{
if($this->app === null) {
$this->app = \app();
}

$loggingConfig = $config;
$cwClient = new CloudWatchLogsClient($this->getCredentials());
$loggingConfig = $this->app->make('config')->get('logging.channels.cloudwatch');

$streamName = $loggingConfig['stream_name'];
$retentionDays = $loggingConfig['retention'];
$groupName = $loggingConfig['group_name'];
$batchSize = isset($loggingConfig['batch_size']) ? $loggingConfig['batch_size'] : 10000;

$logHandler = new CloudWatch($cwClient, $groupName, $streamName, $retentionDays, $batchSize);
$logger = new Logger($loggingConfig['name']);
$logger = new \Monolog\Logger($loggingConfig['name']);

$formatter = $this->resolveFormatter($loggingConfig);
$logHandler->setFormatter($formatter);
Expand All @@ -61,30 +41,12 @@ public function getLogger()
return $logger;
}

/**
* Code "inspired" from here
* https://aws.amazon.com/blogs/developer/php-application-logging-with-amazon-cloudwatch-logs-and-monolog
* Laravel installation mentioned here did not work but PHP with Monolog worked, hence this package.
*/
public function register()
{
$this->mergeConfigFrom(
__DIR__.'/../../config/logging.php',
'logging.channels'
);

if (!$this->app->make('config')->get('logging.channels.cloudwatch.disabled')) {
$this->app->singleton('cloudwatch.logger', function () {
return $this->getLogger();
});
}
}

/**
* This is the way config should be defined in config/logging.php
* in key cloudwatch.
*
* 'cloudwatch' => [
* 'driver' => 'custom',
* 'name' => env('CLOUDWATCH_LOG_NAME', ''),
* 'region' => env('CLOUDWATCH_LOG_REGION', ''),
* 'credentials' => [
Expand All @@ -95,6 +57,7 @@ public function register()
* 'retention' => env('CLOUDWATCH_LOG_RETENTION_DAYS', 14),
* 'group_name' => env('CLOUDWATCH_LOG_GROUP_NAME', 'laravel_app'),
* 'version' => env('CLOUDWATCH_LOG_VERSION', 'latest'),
* 'via' => \Pagevamp\Logger::class,
* ]
*
* @return array
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<?php

namespace Tests\Providers;
namespace Tests;

use Illuminate\Contracts\Config\Repository;
use Illuminate\Contracts\Foundation\Application;
use Mockery;
use Monolog\Formatter\JsonFormatter;
use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\LogglyFormatter;
use Monolog\Logger;
use Pagevamp\Exceptions\IncompleteCloudWatchConfig;
use Pagevamp\Providers\CloudWatchServiceProvider;
use PHPUnit\Framework\TestCase;
use \Mockery;

class CloudWatchServiceProviderTest extends TestCase
class LoggerTest extends TestCase
{

public function testGetLoggerShouldResolveCustomFormatterInstanceFromConfiguration()
{
$cloudwatchConfigs = [
Expand Down Expand Up @@ -55,8 +55,8 @@ public function testGetLoggerShouldResolveCustomFormatterInstanceFromConfigurati
->with(JsonFormatter::class)
->andReturn($formatter);

$provider = new CloudWatchServiceProvider($app);
$logger = $provider->getLogger();
$provider = new \Pagevamp\Logger($app);
$logger = $provider($cloudwatchConfigs);

$this->assertInstanceOf(Logger::class, $logger);
$this->assertNotEmpty($logger->getHandlers());
Expand Down Expand Up @@ -106,8 +106,8 @@ public function testGetLoggerShouldResolveDefaultFormatterInstanceWhenConfigIsNu
->with(JsonFormatter::class)
->andReturn($formatter);

$provider = new CloudWatchServiceProvider($app);
$logger = $provider->getLogger();
$provider = new \Pagevamp\Logger($app);
$logger = $provider($cloudwatchConfigs);

$this->assertInstanceOf(Logger::class, $logger);
$this->assertNotEmpty($logger->getHandlers());
Expand Down Expand Up @@ -156,8 +156,8 @@ public function testGetLoggerShouldResolveDefaultFormatterInstanceWhenConfigIsNo
->with(LineFormatter::class)
->andReturn($formatter);

$provider = new CloudWatchServiceProvider($app);
$logger = $provider->getLogger();
$provider = new \Pagevamp\Logger($app);
$logger = $provider($cloudwatchConfigs);

$this->assertInstanceOf(Logger::class, $logger);
$this->assertNotEmpty($logger->getHandlers());
Expand Down Expand Up @@ -209,8 +209,8 @@ public function testGetLoggerShouldResolveCallableFormatter()
->with(LogglyFormatter::class)
->andReturn($formatter);

$provider = new CloudWatchServiceProvider($app);
$logger = $provider->getLogger();
$provider = new \Pagevamp\Logger($app);
$logger = $provider($cloudwatchConfigs);

$this->assertInstanceOf(Logger::class, $logger);
$this->assertNotEmpty($logger->getHandlers());
Expand Down Expand Up @@ -255,7 +255,7 @@ public function testInvalidFormatterWillThrowException()
->andReturn($config);

$this->expectException(IncompleteCloudWatchConfig::class);
$provider = new CloudWatchServiceProvider($app);
$provider->getLogger();
$provider = new \Pagevamp\Logger($app);
$provider($cloudwatchConfigs);
}
}

0 comments on commit b7a65ba

Please sign in to comment.