chequemotiva / monolog-cloudwatch-handler
Monolog integration with CloudWatch Logs
Requires
- php: ^8.0
- aws/aws-sdk-php: ^3.230
- monolog/monolog: ^2.5
README
Handler for PHP logging library Monolog for sending log entries to AWS CloudWatch Logs service.
Before using this library, it's recommended to get acquainted with the pricing for AWS CloudWatch services.
Disclaimer
This library uses AWS API through AWS PHP SDK, which has limits on concurrent requests; it means that on high concurrent or high load applications it may not work on it's best way. Please consider using another solution such as logging to the stdout and redirecting logs with fluentbit.
Requirements
- PHP ^8.0
- AWS account with proper permissions (see list of permissions below)
Differences with maxbanton/cwh
This library is based on maxbanton/cwh. The main differences are:
- This library does not perform any GET request.
- The CloudWatch Logs sequence token can be stored and reused across requests.
- The log group must exist, it will not be autocreated.
Thanks to these changes the logs are saved faster, and the CloudWatch Logs quotas are optimized.
Features
- Up to 10.000 batch logs sending in order to avoid Rate exceeded errors.
- No GET requests.
- AWS CloudWatch Logs staff lazy loading.
- Suitable for web applications and for long-living CLI daemons and workers.
- Sequence token persistence.
- Log Streams creating.
Installation
Install the latest version with Composer by running
$ composer require chequemotiva/monolog-cloudwatch-handler:1.0.0-rc2
Basic Usage
<?php
use \Aws\CloudWatchLogs\CloudWatchLogsClient;
use \Chequemotiva\Monolog\CloudWatch\CloudWatchHandler;
use \Monolog\Logger;
use \Monolog\Formatter\JsonFormatter;
// Instantiate AWS SDK CloudWatch Logs Client
$client = new CloudWatchLogsClient([
'region' => '<aws-region>',
'version' => 'latest',
'credentials' => [
'key' => '<aws-key>', // AWS access key ID
'secret' => '<aws-secret>', // AWS secret access key
'token' => '<aws-access-token>', // AWS session token (optional)
]
]);
$handler = new CloudWatchHandler(
client: $client,
group: '<log-group-name>', // Existing log group name
stream: '<log-stream-name>', // Log stream name, will be created if it doesn't exist
level: \Psr\Log\LogLevel::DEBUG,
);
// Optionally set the JsonFormatter to be able to access your log messages in a structured way
$handler->setFormatter(new JsonFormatter());
// Create a log channel
$log = new Logger('<logger-name>');
// Set handler
$log->pushHandler($handler);
// Add records to the log
$log->debug('Foo');
$log->warning('Bar');
$log->error('Baz');
Persisting sequence tokens
By default, the CloudWatch Logs sequence token is stored in memory, but the handler can be configured to store it in the
filesystem using the sequenceToken
parameter, so it could be reused in future requests without additional API calls.
use \Chequemotiva\Monolog\CloudWatch\CloudWatchHandler;
use \Chequemotiva\Monolog\CloudWatch\SequenceTokenRepositories\FilesystemSequenceTokenRepository;
$handler = new CloudWatchHandler(
client: $client,
group: '<log-group-name>',
stream: '<log-stream-name>',
sequenceToken: new FilesystemSequenceTokenRepository('<cache-path>'),
);
You can implement your own persistence mechanism by implementing the interface \Chequemotiva\Monolog\CloudWatch\SequenceTokenRepositories\SequenceTokenRepositoryInterface
.
Limiting buffer size
Log events are buffered and sent to CloudWatch Log in batches, up to 10.000 log events. You can
modify this behaviour specifying the eventBuffer
parameter:
use \Chequemotiva\Monolog\CloudWatch\CloudWatchHandler;
use \Chequemotiva\Monolog\CloudWatch\EventBuffers\OverflowEventBuffer;
$handler = new CloudWatchHandler(
client: $client,
group: '<log-group-name>',
stream: '<log-stream-name>',
eventBuffer: new OverflowEventBuffer(1), // Send events one by one
);
Additional buffer strategies can be achieved by implementing the interface \Chequemotiva\Monolog\CloudWatch\EventBuffers\EventBufferInterface
.
AWS IAM needed permissions
The API users needs the following permissions:
AWS IAM Policy full json example
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream"
],
"Resource": "<log-group-arn>"
},
{
"Effect": "Allow",
"Action": [
"logs:PutLogEvents"
],
"Resource": [
"<log-stream-arn-1>",
"<log-stream-arn-2>"
]
}
]
}
Issues
Feel free to report any issues
Contributing
Please check this document