Passed
Push — sheepy/elevation-configuration ( f8fadb...77a4b0 )
by Marco
07:42
created

SolrLogger::setClient()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 5
ccs 3
cts 3
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
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
     * @var Client Guzzle base client to communicate with Solr
36
     */
37
    protected $client;
38
39
    /**
40
     * SolrLogger constructor.
41
     *
42
     * @param null|Countable $handler
43
     */
44 41
    public function __construct($handler = null)
45
    {
46 41
        $config = SolrCoreService::config()->get('config');
47 41
        $hostConfig = array_shift($config['endpoint']);
48
        $guzzleConfig = [
49 41
            'base_uri' => $hostConfig['host'] . ':' . $hostConfig['port'],
50
        ];
51 41
        if ($handler) {
52 1
            $guzzleConfig['handler'] = $handler;
53
        }
54
55 41
        $this->client = new Client($guzzleConfig);
56 41
    }
57
58
    /**
59
     * Log the given message and dump it out.
60
     * Also boot the Log to get the latest errors from Solr
61
     *
62
     * @param string $type
63
     * @param string $message
64
     * @param string $index
65
     * @throws GuzzleException
66
     * @throws ValidationException
67
     */
68 1
    public static function logMessage($type, $message, $index): void
69
    {
70 1
        $solrLogger = new self();
71 1
        $solrLogger->saveSolrLog($type);
72
        /** @var SolrLog $lastError */
73 1
        $lastError = SolrLog::get()
74 1
            ->filter([
75 1
                'Index' => 'x:' . $index,
76 1
                'Level' => $type,
77
            ])
78 1
            ->sort('Timestamp DESC')
79 1
            ->first();
80
81 1
        $err = ($lastError === null) ? 'Unknown' : $lastError->getLastErrorLine();
82 1
        $message .= 'Last known error:' . PHP_EOL . $err;
83
        /** @var LoggerInterface $logger */
84 1
        $logger = Injector::inst()->get(LoggerInterface::class);
85 1
        $logger->alert($message);
86 1
        if (Director::is_cli() || Controller::curr()->getRequest()->getVar('unittest')) {
87 1
            Debug::dump($message);
88
        }
89 1
    }
90
91
    /**
92
     * Save the latest Solr errors to the log
93
     *
94
     * @param string $type
95
     * @throws GuzzleException
96
     * @throws ValidationException
97
     */
98 39
    public function saveSolrLog($type = 'Query'): void
99
    {
100 39
        $response = $this->client->request('GET', 'solr/admin/info/logging', [
101 39
            'query' => [
102
                'since' => 0,
103
                'wt'    => 'json',
104
            ],
105
        ]);
106
107 39
        $arrayResponse = json_decode($response->getBody(), true);
108
109 39
        foreach ($arrayResponse['history']['docs'] as $error) {
110
            $filter = [
111 35
                'Timestamp' => $error['time'],
112 35
                'Index'     => $error['core'] ?? 'x:Unknown',
113 35
                'Level'     => $error['level'],
114
            ];
115 35
            $this->findOrCreateLog($type, $filter, $error);
116
        }
117 39
    }
118
119
    /**
120
     * Attempt to find, otherwise create, a log object
121
     *
122
     * @param $type
123
     * @param array $filter
124
     * @param $error
125
     * @throws ValidationException
126
     */
127 35
    private function findOrCreateLog($type, array $filter, $error): void
128
    {
129
        // Not covered in tests. It's only here to make sure the connection isn't closed by a child process
130 35
        $conn = DB::is_active();
131 35
        if (!$conn) {
132
            $config = DB::getConfig();
133
            DB::connect($config);
134
        }
135 35
        if (!SolrLog::get()->filter($filter)->exists()) {
136
            $logData = [
137 35
                'Message' => $error['message'],
138 35
                'Type'    => $type,
139
            ];
140 35
            $log = array_merge($filter, $logData);
141 35
            SolrLog::create($log)->write();
142 35
            if (Director::is_cli() || Controller::curr()->getRequest()->getVar('unittest')) {
143
                /** @var LoggerInterface $logger */
144 35
                $logger = Injector::inst()->get(LoggerInterface::class);
145 35
                $logger->error($error['message']);
146
            }
147
        }
148 35
    }
149
150
    /**
151
     * Return the Guzzle Client
152
     *
153
     * @return Client
154
     */
155 2
    public function getClient(): Client
156
    {
157 2
        return $this->client;
158
    }
159
160
    /**
161
     * Set the Guzzle client
162
     *
163
     * @param Client $client
164
     * @return SolrLogger
165
     */
166 1
    public function setClient(Client $client): self
167
    {
168 1
        $this->client = $client;
169
170 1
        return $this;
171
    }
172
}
173