Completed
Push — develop ( f0e0d2...1cdaea )
by Mathias
15:25 queued 07:45
created

LogStrategy::__construct()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 13
ccs 7
cts 7
cp 1
rs 10
c 0
b 0
f 0
cc 4
nc 5
nop 1
crap 4
1
<?php
2
/**
3
 * YAWIK
4
 *
5
 * @filesource
6
 * @license MIT
7
 * @copyright  2013 - 2019 Cross Solution <http://cross-solution.de>
8
 */
9
10
declare(strict_types=1);
11
12
/** */
13
namespace Core\Queue\Strategy;
14
15
use SlmQueue\Job\AbstractJob;
16
use SlmQueue\Job\JobInterface;
17
use SlmQueue\Strategy\AbstractStrategy;
18
use SlmQueue\Worker\Event\AbstractWorkerEvent;
19
use SlmQueue\Worker\Event\BootstrapEvent;
20
use SlmQueue\Worker\Event\FinishEvent;
21
use SlmQueue\Worker\Event\ProcessJobEvent;
22
use Zend\EventManager\EventManagerInterface;
23
use Zend\Log\LoggerAwareInterface;
24
use Zend\Log\LoggerInterface;
25
26
/**
27
 * Queue Worker Strategy to log events using an instance of {@link LoggerInterface}
28
 *
29
 * If the processed job implements LoggerAwareInterface, the Logger gets injected
30
 * into the job - unless {@link injectLogger} is false.
31
 * 
32
 * @author Mathias Gelhausen <[email protected]>
33
 * @todo write test 
34
 */
35
class LogStrategy extends AbstractStrategy
36
{
37
    /**
38
     * The logger instance.
39
     *
40
     * @var LoggerInterface
41
     */
42
    private $logger;
43
44
    /**
45
     * Templates for log messages
46
     *
47
     * @var array
48
     */
49
    private $tmpl = [
50
        'queue' => '%s queue: %s',
51
        'job'   => '{ %s } [ %s ] %s',
52
    ];
53
54
    /**
55
     * Inject the logger in the processed job?
56
     *
57
     * @var bool
58
     */
59
    private $injectLogger = true;
60
61
    /**
62
     * LogStrategy constructor.
63
     *
64
     * @param array|LoggerInterface|null $options
65
     */
66 16
    public function __construct($options = null)
67
    {
68 16
        if (null === $options) { return; }
69
70 3
        if ($options instanceOf LoggerInterface) {
71 1
            $options = ['logger' => $options];
72
        }
73
74 3
        if (!is_array($options)) {
0 ignored issues
show
introduced by
The condition is_array($options) is always true.
Loading history...
75 1
            throw new \InvalidArgumentException('Options must be of type array or ' . LoggerInterface::class);
76
        }
77
78 2
        parent::__construct($options);
79 2
    }
80
81
    /**
82
     * Set the logger instance
83
     *
84
     * @param LoggerInterface $logger
85
     */
86 11
    public function setLogger(Loggerinterface $logger) : void
87
    {
88 11
        $this->logger = $logger;
89 11
    }
90
91
    /**
92
     * Get the logger instance
93
     *
94
     * If no instance is set yet, it will return an instance of
95
     * an anonymous class implemeting LoggerInterface which does nothing.
96
     *
97
     * @return LoggerInterface
98
     */
99 9
    public function getLogger() : LoggerInterface
100
    {
101 9
        if (!$this->logger) {
102
            $logger = new class implements LoggerInterface
103
            {
104
                public function emerg($message, $extra = []) : void {}
105
                public function alert($message, $extra = []) : void {}
106
                public function crit($message, $extra = []) : void {}
107
                public function err($message, $extra = []) : void {}
108
                public function warn($message, $extra = []) : void {}
109
                public function notice($message, $extra = []) : void {}
110
                public function info($message, $extra = []) : void {}
111
                public function debug($message, $extra = []) : void {}
112
            };
113 1
            $this->setLogger($logger);
114
        }
115
116 9
        return $this->logger;
117
    }
118
119
    /**
120
     * Set the template for queue events log messages
121
     *
122
     * @param string $template
123
     */
124 2
    public function setLogQueueEventsTemplate(string $template) : void
125
    {
126 2
        $this->tmpl['queue'] = $template;
127 2
    }
128
129
    /**
130
     * Set the template for job events log messages.
131
     *
132
     * @param string $template
133
     */
134 2
    public function setLogJobEventsTemplate(string $template) : void
135
    {
136 2
        $this->tmpl['job'] = $template;
137 2
    }
138
139
    /**
140
     * Set or get the injectLogger flag
141
     *
142
     * If called with an argument, sets the flag accordingly and returns
143
     * it.
144
     *
145
     * @param bool|null $flag
146
     * @return bool
147
     */
148 4
    public function injectLogger(bool $flag = null) : bool
149
    {
150 4
        if (null === $flag) { return $this->injectLogger; }
151
152 1
        $this->injectLogger = $flag;
153 1
        return $flag;
154
    }
155
156
    /**
157
     * Registers itself with an EventManager
158
     *
159
     * @param EventManagerInterface $events
160
     * @param int                   $priority
161
     */
162 1
    public function attach(EventManagerInterface $events, $priority = 1) : void
163
    {
164 1
        $this->listeners[] = $events->attach(AbstractWorkerEvent::EVENT_BOOTSTRAP, [$this, 'logBootstrap'], 1000);
165 1
        $this->listeners[] = $events->attach(AbstractWorkerEvent::EVENT_FINISH, [$this, 'logFinish'], 1000);
166 1
        $this->listeners[] = $events->attach(AbstractWorkerEvent::EVENT_PROCESS_JOB, [$this, 'logJobStart'], 1000);
167 1
        $this->listeners[] = $events->attach(AbstractWorkerEvent::EVENT_PROCESS_JOB, [$this, 'logJobEnd'], -1000);
168 1
        $this->listeners[] = $events->attach(AbstractWorkerEvent::EVENT_PROCESS_IDLE, [$this, 'injectLoggerInEvent'], 1000);
169 1
        $this->listeners[] = $events->attach(AbstractWorkerEvent::EVENT_PROCESS_STATE, [$this, 'injectLoggerInEvent'], 1000);
170 1
    }
171
172
    /**
173
     * Listener method for queue bootstrap event
174
     *
175
     * @param BootstrapEvent $event
176
     */
177 1
    public function logBootstrap(BootstrapEvent $event) : void
178
    {
179 1
        $this->getLogger()->info(sprintf(
180 1
            $this->tmpl['queue'],
181 1
            'Start',
182 1
            $event->getQueue()->getName()
183
        ));
184
185 1
        $this->injectLoggerInObject($event->getWorker());
0 ignored issues
show
Bug introduced by
It seems like $event->getWorker() can also be of type string; however, parameter $object of Core\Queue\Strategy\LogS...:injectLoggerInObject() does only seem to accept object, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

185
        $this->injectLoggerInObject(/** @scrutinizer ignore-type */ $event->getWorker());
Loading history...
186 1
        $this->injectLoggerInEvent($event);
187 1
    }
188
189
    /**
190
     * Listener method for queue finish event
191
     *
192
     * @param FinishEvent $event
193
     */
194 1
    public function logFinish(FinishEvent $event) : void
195
    {
196 1
        $this->getLogger()->info(sprintf(
197 1
            $this->tmpl['queue'],
198 1
            'Stop',
199 1
            $event->getQueue()->getName()
200
        ));
201
202 1
        $this->injectLoggerInEvent($event);
203 1
    }
204
205
    /**
206
     * listener method for process job event.
207
     *
208
     * Called early due to high priority.
209
     *
210
     * @param ProcessJobEvent $event
211
     */
212 2
    public function logJobStart(ProcessJobEvent $event) : void
213
    {
214 2
        $queue  = $event->getQueue();
215 2
        $job    = $event->getJob();
216 2
        $logger = $this->getLogger();
217
218 2
        $logger->info(sprintf(
219 2
            $this->tmpl['job'],
220 2
            $queue->getName(),
221 2
            'START',
222 2
            $this->formatJob($job),
223 2
            ''
224
        ));
225
226 2
        $this->injectLoggerInObject($job);
227 2
        $this->injectLoggerInEvent($event);
228 2
    }
229
230
    /**
231
     * listener method for process job event
232
     *
233
     * Called late due to low priority
234
     *
235
     * @param ProcessJobEvent $event
236
     */
237 4
    public function logJobEnd(ProcessJobEvent $event) : void
238
    {
239 4
        $result  = $event->getResult();
240 4
        $job     = $event->getJob();
241 4
        $queue   = $event->getQueue()->getName();
242 4
        $logger  = $this->getLogger();
243
244 4
        switch ($result) {
245
            default:
246
247 2
                $logger->info(sprintf(
248 2
                    $this->tmpl['job'],
249 2
                    $queue,
250 2
                    'SUCCESS',
251 2
                    $this->formatJob($job)
252
                ));
253 2
                break;
254
255
            case ProcessJobEvent::JOB_STATUS_FAILURE_RECOVERABLE:
256 1
                $logger->warn(sprintf(
257 1
                    $this->tmpl['job'],
258 1
                    $queue,
259 1
                    'RECOVERABLE',
260 1
                    $this->formatJob($job)
261
                ));
262
263 1
                break;
264
265
            case ProcessJobEvent::JOB_STATUS_FAILURE:
266 1
                $logger->err(sprintf(
267 1
                    $this->tmpl['job'],
268 1
                    $queue,
269 1
                    'FAILURE',
270 1
                    $this->formatJob($job)
271
                ));
272
273 1
                break;
274
        }
275 4
    }
276
277 3
    public function injectLoggerInEvent(AbstractWorkerEvent $event)
278
    {
279 3
        if ($this->injectLogger()) {
280 3
            $event->setParam('logger', $this->getLogger());
281
        }
282 3
    }
283
284 3
    private function injectLoggerInObject(object $object) : void
285
    {
286 3
        if ($this->injectLogger() && $object instanceOf LoggerAwareInterface) {
287 1
            $object->setLogger($this->getLogger());
288
        }
289 3
    }
290
291
    /**
292
     * Get a string representation of the processed job instance
293
     *
294
     * @param JobInterface $job
295
     *
296
     * @return string
297
     */
298 6
    private function formatJob(JobInterface $job) : string
299
    {
300 6
        return get_class($job) . ' [ ' . $job->getId() . ' ] ';
301
    }
302
303
}
304