3 * @copyright Copyright (C) 2010-2022, the Friendica project
5 * @license GNU AGPL version 3 or any later version
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 namespace Friendica\Object\Log;
25 * Parse a log line and offer some utility methods
29 const REGEXP = '/^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[^ ]*) (\w+) \[(\w*)\]: (.*)/';
38 public $context = null;
44 public $message = null;
50 public $source = null;
57 * @param string $logline Source log line to parse
59 public function __construct(int $id, string $logline)
62 $this->parse($logline);
65 private function parse($logline)
67 $this->logline = $logline;
69 // if data is empty is serialized as '[]'. To ease the parsing
70 // let's replace it with '{""}'. It will be replaced by null later
71 $logline = str_replace(' [] - {', ' {""} - {', $logline);
74 if (strstr($logline, ' - {') === false) {
75 // the log line is not well formed
78 // here we hope that there will not be the string ' - {' inside the $jsonsource value
79 list($logline, $jsonsource) = explode(' - {', $logline);
80 $jsonsource = '{' . $jsonsource;
84 if (strpos($logline, '{"') > 0) {
85 list($logline, $jsondata) = explode('{"', $logline, 2);
87 $jsondata = '{"' . $jsondata;
90 preg_match(self::REGEXP, $logline, $matches);
92 if (count($matches) == 0) {
93 // regexp not matching
94 $this->message = $this->logline;
96 $this->date = $matches[1];
97 $this->context = $matches[2];
98 $this->level = $matches[3];
99 $this->message = $matches[4];
100 $this->data = $jsondata == '{""}' ? null : $jsondata;
101 $this->source = $jsonsource;
105 $this->message = trim($this->message);
109 * Fix message / data split
111 * In log boundary between message and json data is not specified.
112 * If message contains '{' the parser thinks there starts the json data.
113 * This method try to parse the found json and if it fails, search for next '{'
114 * in json data and retry
116 private function tryfixjson()
118 if (is_null($this->data) || $this->data == '') {
122 $d = json_decode($this->data, true, 512, JSON_THROW_ON_ERROR);
123 } catch (\JsonException $e) {
124 // try to find next { in $str and move string before to 'message'
126 $pos = strpos($this->data, '{', 1);
127 if ($pos === false) {
128 $this->message .= $this->data;
133 $this->message .= substr($this->data, 0, $pos);
134 $this->data = substr($this->data, $pos);
140 * Return decoded `data` as array suitable for template
144 public function getData()
146 $data = json_decode($this->data, true);
148 foreach ($data as $k => $v) {
149 $data[$k] = print_r($v, true);
156 * Return decoded `source` as array suitable for template
160 public function getSource()
162 return json_decode($this->source, true);