Passed
Push — hans/code-cleaning ( b3cc5f...fbec82 )
by Simon
04:59 queued 02:36
created

SolrLogger   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Test Coverage

Coverage 96.23%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 50
c 3
b 0
f 0
dl 0
loc 141
ccs 51
cts 53
cp 0.9623
rs 10
wmc 15

6 Methods

Rating   Name   Duplication   Size   Complexity  
A findOrCreateLog() 0 19 5
A setClient() 0 5 1
A saveSolrLog() 0 18 2
A logMessage() 0 20 4
A getClient() 0 3 1
A __construct() 0 12 2
1
<?php
2
/**
3
 * class SolrLogger|Firesphere\SolrSearch\Helpers\SolrLogger Log errors to the Database
4
 *
5
 * @package Firesphere\SolrSearch\Helpers
6
 * @author Simon `Firesphere` Erkelens; Marco `Sheepy` Hermo
7
 * @copyright Copyright (c) 2018 - now() Firesphere & Sheepy
8
 */
9
10
namespace Firesphere\SolrSearch\Helpers;
11
12
use Countable;
13
use Firesphere\SolrSearch\Models\SolrLog;
14
use Firesphere\SolrSearch\Services\SolrCoreService;
15
use GuzzleHttp\Client;
16
use GuzzleHttp\Exception\GuzzleException;
17
use Psr\Log\LoggerInterface;
18
use SilverStripe\Control\Controller;
19
use SilverStripe\Control\Director;
20
use SilverStripe\Core\Injector\Injector;
21
use SilverStripe\Dev\Debug;
22
use SilverStripe\ORM\DB;
23
use SilverStripe\ORM\ValidationException;
24
25
/**
26
 * Class SolrLogger
27
 *
28
 * Log information from Solr to the CMS for reference
29
 *
30
 * @package Firesphere\SolrSearch\Helpers
31
 */
32
class SolrLogger
33
{
34
    /**
35
     * Guzzle base client to communicate with Solr
36
     *
37
     * @var Client
38
     */
39
    protected $client;
40
41
    /**
42
     * SolrLogger constructor.
43
     *
44
     * @param null|Countable $handler
45
     */
46 41
    public function __construct($handler = null)
47
    {
48 41
        $config = SolrCoreService::config()->get('config');
49 41
        $hostConfig = array_shift($config['endpoint']);
50
        $guzzleConfig = [
51 41
            'base_uri' => $hostConfig['host'] . ':' . $hostConfig['port'],
52
        ];
53 41
        if ($handler) {
54 1
            $guzzleConfig['handler'] = $handler;
55
        }
56
57 41
        $this->client = new Client($guzzleConfig);
58 41
    }
59
60
    /**
61
     * Log the given message and dump it out.
62
     * Also boot the Log to get the latest errors from Solr
63
     *
64
     * @param string $type
65
     * @param string $message
66
     * @param string $index
67
     * @throws GuzzleException
68
     * @throws ValidationException
69
     */
70 1
    public static function logMessage($type, $message, $index): void
71
    {
72 1
        $solrLogger = new self();
73 1
        $solrLogger->saveSolrLog($type);
74
        /** @var SolrLog $lastError */
75 1
        $lastError = SolrLog::get()
76 1
            ->filter([
77 1
                'Index' => 'x:' . $index,
78 1
                'Level' => $type,
79
            ])
80 1
            ->sort('Timestamp DESC')
81 1
            ->first();
82
83 1
        $err = ($lastError === null) ? 'Unknown' : $lastError->getLastErrorLine();
84 1
        $message .= 'Last known error:' . PHP_EOL . $err;
85
        /** @var LoggerInterface $logger */
86 1
        $logger = Injector::inst()->get(LoggerInterface::class);
87 1
        $logger->alert($message);
88 1
        if (Director::is_cli() || Controller::curr()->getRequest()->getVar('unittest')) {
89 1
            Debug::dump($message);
90
        }
91 1
    }
92
93
    /**
94
     * Save the latest Solr errors to the log
95
     *
96
     * @param string $type
97
     * @throws GuzzleException
98
     * @throws ValidationException
99
     */
100 39
    public function saveSolrLog($type = 'Query'): void
101
    {
102 39
        $response = $this->client->request('GET', 'solr/admin/info/logging', [
103 39
            'query' => [
104
                'since' => 0,
105
                'wt'    => 'json',
106
            ],
107
        ]);
108
109 39
        $arrayResponse = json_decode($response->getBody(), true);
110
111 39
        foreach ($arrayResponse['history']['docs'] as $error) {
112
            $filter = [
113 39
                'Timestamp' => $error['time'],
114 39
                'Index'     => $error['core'] ?? 'x:Unknown',
115 39
                'Level'     => $error['level'],
116
            ];
117 39
            $this->findOrCreateLog($type, $filter, $error);
118
        }
119 39
    }
120
121
    /**
122
     * Attempt to find, otherwise create, a log object
123
     *
124
     * @param $type
125
     * @param array $filter
126
     * @param $error
127
     * @throws ValidationException
128
     */
129 39
    private function findOrCreateLog($type, array $filter, $error): void
130
    {
131
        // Not covered in tests. It's only here to make sure the connection isn't closed by a child process
132 39
        $conn = DB::is_active();
133 39
        if (!$conn) {
134
            $config = DB::getConfig();
135
            DB::connect($config);
136
        }
137 39
        if (!SolrLog::get()->filter($filter)->exists()) {
138
            $logData = [
139 39
                'Message' => $error['message'],
140 39
                'Type'    => $type,
141
            ];
142 39
            $log = array_merge($filter, $logData);
143 39
            SolrLog::create($log)->write();
144 39
            if (Director::is_cli() || Controller::curr()->getRequest()->getVar('unittest')) {
145
                /** @var LoggerInterface $logger */
146 39
                $logger = Injector::inst()->get(LoggerInterface::class);
147 39
                $logger->error($error['message']);
148
            }
149
        }
150 39
    }
151
152
    /**
153
     * Return the Guzzle Client
154
     *
155
     * @return Client
156
     */
157 2
    public function getClient(): Client
158
    {
159 2
        return $this->client;
160
    }
161
162
    /**
163
     * Set the Guzzle client
164
     *
165
     * @param Client $client
166
     * @return SolrLogger
167
     */
168 1
    public function setClient(Client $client): self
169
    {
170 1
        $this->client = $client;
171
172 1
        return $this;
173
    }
174
}
175