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