5

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.

josef.van.niekerk
  • 11,941
  • 20
  • 97
  • 157
  • You could look into fluentd, it's a very good tool, but if you need real time logging to S3, it might not be the best choice. – Petar Zivkovic Sep 14 '14 at 21:46

1 Answers1

6

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.

josef.van.niekerk
  • 11,941
  • 20
  • 97
  • 157