1<?php declare(strict_types=1);
2
3/*
4 * This file is part of the Monolog package.
5 *
6 * (c) Jordi Boggiano <j.boggiano@seld.be>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Monolog\Handler;
13
14use Aws\Sdk;
15use Aws\DynamoDb\DynamoDbClient;
16use Monolog\Formatter\FormatterInterface;
17use Aws\DynamoDb\Marshaler;
18use Monolog\Formatter\ScalarFormatter;
19use Monolog\Logger;
20
21/**
22 * Amazon DynamoDB handler (http://aws.amazon.com/dynamodb/)
23 *
24 * @link https://github.com/aws/aws-sdk-php/
25 * @author Andrew Lawson <adlawson@gmail.com>
26 */
27class DynamoDbHandler extends AbstractProcessingHandler
28{
29    public const DATE_FORMAT = 'Y-m-d\TH:i:s.uO';
30
31    /**
32     * @var DynamoDbClient
33     */
34    protected $client;
35
36    /**
37     * @var string
38     */
39    protected $table;
40
41    /**
42     * @var int
43     */
44    protected $version;
45
46    /**
47     * @var Marshaler
48     */
49    protected $marshaler;
50
51    /**
52     * @param int|string $level
53     */
54    public function __construct(DynamoDbClient $client, string $table, $level = Logger::DEBUG, bool $bubble = true)
55    {
56        /** @phpstan-ignore-next-line */
57        if (defined('Aws\Sdk::VERSION') && version_compare(Sdk::VERSION, '3.0', '>=')) {
58            $this->version = 3;
59            $this->marshaler = new Marshaler;
60        } else {
61            $this->version = 2;
62        }
63
64        $this->client = $client;
65        $this->table = $table;
66
67        parent::__construct($level, $bubble);
68    }
69
70    /**
71     * {@inheritdoc}
72     */
73    protected function write(array $record): void
74    {
75        $filtered = $this->filterEmptyFields($record['formatted']);
76        if ($this->version === 3) {
77            $formatted = $this->marshaler->marshalItem($filtered);
78        } else {
79            /** @phpstan-ignore-next-line */
80            $formatted = $this->client->formatAttributes($filtered);
81        }
82
83        $this->client->putItem([
84            'TableName' => $this->table,
85            'Item' => $formatted,
86        ]);
87    }
88
89    protected function filterEmptyFields(array $record): array
90    {
91        return array_filter($record, function ($value) {
92            return !empty($value) || false === $value || 0 === $value;
93        });
94    }
95
96    /**
97     * {@inheritdoc}
98     */
99    protected function getDefaultFormatter(): FormatterInterface
100    {
101        return new ScalarFormatter(self::DATE_FORMAT);
102    }
103}
104