• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mimmi20 / monolog-factory / 18427067299

11 Oct 2025 08:38AM UTC coverage: 87.812% (-0.07%) from 87.88%
18427067299

push

github

web-flow
Merge pull request #912 from mimmi20/dependabot/master/maintenance_master-1893dd32ff

Bump the "maintenance-master" group with 1 updates across multiple ecosystems

2572 of 2929 relevant lines covered (87.81%)

16.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.94
/src/Handler/ElasticsearchHandlerFactory.php
1
<?php
2

3
/**
4
 * This file is part of the mimmi20/monolog-factory package.
5
 *
6
 * Copyright (c) 2022-2025, Thomas Mueller <mimmi20@live.de>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11

12
declare(strict_types = 1);
13

14
namespace Mimmi20\MonologFactory\Handler;
15

16
use Elastic\Elasticsearch\Client as V8Client;
17
use Elasticsearch\Client as V7Client;
18
use Laminas\ServiceManager\AbstractPluginManager;
19
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
20
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
21
use Laminas\ServiceManager\Factory\FactoryInterface;
22
use Mimmi20\MonologFactory\AddFormatterTrait;
23
use Mimmi20\MonologFactory\AddProcessorTrait;
24
use Mimmi20\MonologFactory\ClientPluginManager;
25
use Monolog\Handler\ElasticsearchHandler;
26
use Monolog\Level;
27
use Override;
28
use Psr\Container\ContainerExceptionInterface;
29
use Psr\Container\ContainerInterface;
30
use Psr\Log\LogLevel;
31

32
use function array_key_exists;
33
use function assert;
34
use function class_exists;
35
use function date;
36
use function get_debug_type;
37
use function in_array;
38
use function is_array;
39
use function is_string;
40
use function mb_strpos;
41
use function sprintf;
42
use function str_replace;
43

44
final class ElasticsearchHandlerFactory implements FactoryInterface
45
{
46
    use AddFormatterTrait;
47
    use AddProcessorTrait;
48

49
    /** @api */
50
    public const string INDEX_PER_DAY = 'Y-m-d';
51

52
    /** @api */
53
    public const string INDEX_PER_MONTH = 'Y-m';
54

55
    /** @api */
56
    public const string INDEX_PER_YEAR = 'Y';
57

58
    /**
59
     * @param array<string, (bool|int|string|V7Client|V8Client)>|null $options
60
     * @phpstan-param array{client?: (bool|string|V7Client|V8Client), index?: string, type?: string, ignoreError?: bool, level?: (value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::*), bubble?: bool}|null $options
61
     *
62
     * @throws ServiceNotFoundException   if unable to resolve the service
63
     * @throws ServiceNotCreatedException if an exception is raised when creating a service
64
     *
65
     * @phpcsSuppress SlevomatCodingStandard.Functions.UnusedParameter.UnusedParameter
66
     */
67
    #[Override]
40✔
68
    public function __invoke(
69
        ContainerInterface $container,
70
        string $requestedName,
71
        array | null $options = null,
72
    ): ElasticsearchHandler {
73
        if (!is_array($options)) {
40✔
74
            throw new ServiceNotCreatedException('Options must be an Array');
2✔
75
        }
76

77
        if (!array_key_exists('client', $options)) {
38✔
78
            throw new ServiceNotCreatedException(
2✔
79
                'No Service name provided for the required service class',
2✔
80
            );
2✔
81
        }
82

83
        if ($options['client'] instanceof V8Client || $options['client'] instanceof V7Client) {
36✔
84
            $client = $options['client'];
2✔
85
        } elseif (is_array($options['client'])) {
34✔
86
            $clientType = class_exists(V8Client::class) ? V8Client::class : V7Client::class;
8✔
87

88
            try {
89
                $monologClientPluginManager = $container->get(ClientPluginManager::class);
8✔
90
            } catch (ContainerExceptionInterface $e) {
2✔
91
                throw new ServiceNotFoundException(
2✔
92
                    sprintf('Could not find service %s', ClientPluginManager::class),
2✔
93
                    0,
2✔
94
                    $e,
2✔
95
                );
2✔
96
            }
97

98
            assert(
6✔
99
                $monologClientPluginManager instanceof ClientPluginManager || $monologClientPluginManager instanceof AbstractPluginManager,
6✔
100
                sprintf(
6✔
101
                    '$monologConfigPluginManager should be an Instance of %s, but was %s',
6✔
102
                    AbstractPluginManager::class,
6✔
103
                    get_debug_type($monologClientPluginManager),
6✔
104
                ),
6✔
105
            );
6✔
106

107
            try {
108
                $client = $monologClientPluginManager->build($clientType, $options['client']);
6✔
109
            } catch (ContainerExceptionInterface $e) {
2✔
110
                throw new ServiceNotFoundException(
2✔
111
                    sprintf('Could not find service %s', $clientType),
2✔
112
                    0,
2✔
113
                    $e,
2✔
114
                );
2✔
115
            }
116

117
            if (!$client instanceof V8Client && !$client instanceof V7Client) {
4✔
118
                throw new ServiceNotCreatedException(
2✔
119
                    sprintf('Could not create %s', $clientType),
2✔
120
                );
2✔
121
            }
122
        } elseif (!is_string($options['client'])) {
26✔
123
            throw new ServiceNotCreatedException(
2✔
124
                'No Service name provided for the required service class',
2✔
125
            );
2✔
126
        } else {
127
            try {
128
                $client = $container->get($options['client']);
24✔
129
            } catch (ContainerExceptionInterface $e) {
2✔
130
                throw new ServiceNotFoundException(
2✔
131
                    sprintf('Could not load client class for %s class', ElasticsearchHandler::class),
2✔
132
                    0,
2✔
133
                    $e,
2✔
134
                );
2✔
135
            }
136

137
            if (!$client instanceof V8Client && !$client instanceof V7Client) {
22✔
138
                throw new ServiceNotCreatedException(
2✔
139
                    sprintf('Could not create %s', ElasticsearchHandler::class),
2✔
140
                );
2✔
141
            }
142
        }
143

144
        $index           = 'monolog';
24✔
145
        $dateFormat      = self::INDEX_PER_DAY;
24✔
146
        $indexNameFormat = '{indexname}';
24✔
147
        $type            = 'record';
24✔
148
        $ignoreError     = false;
24✔
149
        $level           = LogLevel::DEBUG;
24✔
150
        $bubble          = true;
24✔
151

152
        if (array_key_exists('index', $options)) {
24✔
153
            $index = $options['index'];
20✔
154
        }
155

156
        if (
157
            array_key_exists('dateFormat', $options)
24✔
158
            && in_array(
24✔
159
                $options['dateFormat'],
24✔
160
                [self::INDEX_PER_DAY, self::INDEX_PER_MONTH, self::INDEX_PER_YEAR],
24✔
161
                true,
24✔
162
            )
24✔
163
        ) {
164
            $dateFormat = $options['dateFormat'];
×
165
        }
166

167
        if (
168
            array_key_exists('indexNameFormat', $options)
24✔
169
            && is_string($options['indexNameFormat'])
24✔
170
            && mb_strpos($options['indexNameFormat'], '{indexname}') !== false
24✔
171
        ) {
172
            $indexNameFormat = $options['indexNameFormat'];
×
173
        }
174

175
        if (array_key_exists('type', $options)) {
24✔
176
            $type = $options['type'];
20✔
177
        }
178

179
        if (array_key_exists('ignoreError', $options)) {
24✔
180
            $ignoreError = $options['ignoreError'];
20✔
181
        }
182

183
        if (array_key_exists('level', $options)) {
24✔
184
            $level = $options['level'];
20✔
185
        }
186

187
        if (array_key_exists('bubble', $options)) {
24✔
188
            $bubble = $options['bubble'];
20✔
189
        }
190

191
        $handler = new ElasticsearchHandler(
24✔
192
            $client,
24✔
193
            [
24✔
194
                'ignore_error' => $ignoreError,
24✔
195
                'index' => str_replace(
24✔
196
                    ['{indexname}', '{date}'],
24✔
197
                    [$index, date($dateFormat)],
24✔
198
                    $indexNameFormat,
24✔
199
                ),
24✔
200
                'type' => $type,
24✔
201
            ],
24✔
202
            $level,
24✔
203
            $bubble,
24✔
204
        );
24✔
205

206
        $this->addFormatter($container, $handler, $options);
24✔
207
        $this->addProcessor($container, $handler, $options);
18✔
208

209
        return $handler;
10✔
210
    }
211
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc