Completed
Push — develop ( f102ca...488b09 )
by Mathias
20:12 queued 11:00
created

LogStrategy::logJobEnd()

Size

Total Lines 42
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 31
dl 0
loc 42
ccs 29
cts 29
cp 1
c 0
b 0
f 0
nc 3
nop 1
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%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 2
    public function injectLogger(bool $flag = null) : bool
149
    {
150 2
        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']);
165 1
        $this->listeners[] = $events->attach(AbstractWorkerEvent::EVENT_FINISH, [$this, 'logFinish']);
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
    }
169
170
    /**
171
     * Listener method for queue bootstrap event
172
     *
173
     * @param BootstrapEvent $event
174
     */
175 1
    public function logBootstrap(BootstrapEvent $event) : void
176
    {
177 1
        $this->getLogger()->info(sprintf(
178 1
            $this->tmpl['queue'],
179 1
            'Start',
180 1
            $event->getQueue()->getName()
181
        ));
182 1
    }
183
184
    /**
185
     * Listener method for queue finish event
186
     *
187
     * @param FinishEvent $event
188
     */
189 1
    public function logFinish(FinishEvent $event) : void
190
    {
191 1
        $this->getLogger()->info(sprintf(
192 1
            $this->tmpl['queue'],
193 1
            'Stop',
194 1
            $event->getQueue()->getName()
195
        ));
196 1
    }
197
198
    /**
199
     * listener method for process job event.
200
     *
201
     * Called early due to high priority.
202
     *
203
     * @param ProcessJobEvent $event
204
     */
205 2
    public function logJobStart(ProcessJobEvent $event) : void
206
    {
207 2
        $queue  = $event->getQueue();
208 2
        $job    = $event->getJob();
209 2
        $logger = $this->getLogger();
210
211 2
        $logger->info(sprintf(
212 2
            $this->tmpl['job'],
213 2
            $queue->getName(),
214 2
            'START',
215 2
            $this->formatJob($job),
216 2
            ''
217
        ));
218
219 2
        if ($job instanceOf LoggerAwareInterface && $this->injectLogger()) {
220 1
            $job->setLogger($logger);
221
        }
222 2
    }
223
224
    /**
225
     * listener method for process job event
226
     *
227
     * Called late due to low priority
228
     *
229
     * @param ProcessJobEvent $event
230
     */
231 4
    public function logJobEnd(ProcessJobEvent $event) : void
232
    {
233 4
        $result  = $event->getResult();
234 4
        $job     = $event->getJob();
235 4
        $queue   = $event->getQueue()->getName();
236 4
        $logger  = $this->getLogger();
237
238 4
        switch ($result) {
239
            default:
240
241 2
                $logger->info(sprintf(
242 2
                    $this->tmpl['job'],
243 2
                    $queue,
244 2
                    'SUCCESS',
245 2
                    $this->formatJob($job),
246 2
                    ''
247
                ));
248 2
                break;
249
250
            case ProcessJobEvent::JOB_STATUS_FAILURE_RECOVERABLE:
251 1
                $reason = $job->getMetadata('log.reason');
252 1
                $logger->warn(sprintf(
253 1
                    $this->tmpl['job'],
254 1
                    $queue,
255 1
                    'RECOVERABLE',
256 1
                    $this->formatJob($job),
257 1
                    ": $reason"
258
                ));
259
260 1
                break;
261
262
            case ProcessJobEvent::JOB_STATUS_FAILURE:
263 1
                $reason = $job->getMetadata('log.reason');
264 1
                $logger->err(sprintf(
265 1
                    $this->tmpl['job'],
266 1
                    $queue,
267 1
                    'FAILURE',
268 1
                    $this->formatJob($job),
269 1
                    ": $reason"
270
                ));
271
272 1
                break;
273
        }
274 4
    }
275
276
    /**
277
     * Get a string representation of the processed job instance
278
     *
279
     * @param JobInterface $job
280
     *
281
     * @return string
282
     */
283 6
    private function formatJob(JobInterface $job) : string
284
    {
285 6
        return get_class($job) . ' [ ' . $job->getId() . ' ] ';
286
    }
287
288
}
289