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    public function __construct(DynamoDbClient $client, string $table, $level = Logger::DEBUG, bool $bubble = true)
52    {
53        /** @phpstan-ignore-next-line */
54        if (defined('Aws\Sdk::VERSION') && version_compare(Sdk::VERSION, '3.0', '>=')) {
55            $this->version = 3;
56            $this->marshaler = new Marshaler;
57        } else {
58            $this->version = 2;
59        }
60
61        $this->client = $client;
62        $this->table = $table;
63
64        parent::__construct($level, $bubble);
65    }
66
67    /**
68     * {@inheritDoc}
69     */
70    protected function write(array $record): void
71    {
72        $filtered = $this->filterEmptyFields($record['formatted']);
73        if ($this->version === 3) {
74            $formatted = $this->marshaler->marshalItem($filtered);
75        } else {
76            /** @phpstan-ignore-next-line */
77            $formatted = $this->client->formatAttributes($filtered);
78        }
79
80        $this->client->putItem([
81            'TableName' => $this->table,
82            'Item' => $formatted,
83        ]);
84    }
85
86    /**
87     * @param  mixed[] $record
88     * @return mixed[]
89     */
90    protected function filterEmptyFields(array $record): array
91    {
92        return array_filter($record, function ($value) {
93            return !empty($value) || false === $value || 0 === $value;
94        });
95    }
96
97    /**
98     * {@inheritDoc}
99     */
100    protected function getDefaultFormatter(): FormatterInterface
101    {
102        return new ScalarFormatter(self::DATE_FORMAT);
103    }
104}
105