Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configure PHP Monolog to log to Amazon S3 via stream

We're using Monolog to log output from our server side PHP worker scripts, that execute on Amazon Elastic Beanstalk EC2 server instances. It's rather hard to access log files, especially considering that servers start up and shut down as scaling demand changes.

How can I configure Monolog to log directly to an Amazon S3 stream/bucket?

So far I'm trying something like this in my Pimple dependency injection definitions:

$this->container['log'] = function ($c) {
    $logger = new \Monolog\Logger('psd_worker');
    $handler = new \Monolog\Handler\StreamHandler('s3://mybucket/logs/test.log');
    $logger->pushHandler($handler);
    return $logger;
};

but no log file is appearing on the bucket, neither am I getting any exceptions.

A little test reveals that I can write through s3:// to the S3 bucket:

$stream = fopen("s3://{$bucket}/{$key}", 'w');
fwrite($stream, 'Hello S3 World!');
fclose($stream);

but I want Monologs logging functions to write to this bucket.

like image 455
josef.van.niekerk Avatar asked Jun 17 '14 19:06

josef.van.niekerk


People also ask

Does PHP work in S3?

S3 doesn't run any sort of CGI script (PHP, Perl, Ruby, etc). Think of it as a static html and image repository. If you want to host your PHP application on AWS, consider using AWS Beanstalk.

How can I read S3 file in PHP?

php'; $s3 = new Aws\S3\S3Client([ 'region' => 'your region', 'version' => 'latest', 'credentials' => [ 'key' => "Your Key Id", 'secret' => "Your secret access key", ] ]); // Send a PutObject request and get the result object.

What is PHP monolog?

Monolog is the existing standard logging library for PHP. It is most popular in PHP frameworks such as Laravel and Symfony, where it implements a common interface for logging libraries.


1 Answers

Managed to get it working. First make an Amazon S3 DI service, making sure to call $s3_client->registerStreamWrapper():

    $this->container['s3_client'] = function ($c) {
        $s3_client = \Aws\S3\S3Client::factory([
            'key' => Config::get('amazon_s3.key'),
            'secret' => Config::get('amazon_s3.secret')
        ]);
        $s3_client->registerStreamWrapper();
        return $s3_client;
    };

then the logger, which should call s3_client to ensure the stream wrapper registration is made:

    $this->container['log'] = function ($c) {
        $this->container['s3_client'];

        $logger = new \Monolog\Logger('psd_worker');
        $handler = new \Monolog\Handler\StreamHandler("s3://mybucket/logs/monolog_s3.log");
        $logger->pushHandler($handler);

        return $logger;
    };

Then, when calling the logger's logging methods:

    $log = $this->container['log'];
    $log->info("Another from Monolog to Amazon S3!!!");

Will result in the data being written to the configured bucket. It appears the data is only written when fclose() is called, would be nice to be able to see the log grow live, but I'm guessing that's going to need a socket approach.

like image 71
josef.van.niekerk Avatar answered Oct 07 '22 01:10

josef.van.niekerk