Skip to content

Commit 6913998

Browse files
authored
Merge pull request #21 from understand/2.0
2.0
2 parents 925ecf1 + 1013f66 commit 6913998

22 files changed

+761
-674
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
composer.phar
33
composer.lock
44
.DS_Store
5+
.idea

README.md

Lines changed: 45 additions & 216 deletions
Large diffs are not rendered by default.

composer.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "understand/understand-laravel5",
33
"description": "Laravel 5 service provider for Understand.io",
4-
"keywords": ["laravel", "undertstand.io", "understand", "logs", "laravel 5"],
4+
"keywords": ["laravel", "understand.io", "understand", "logs", "laravel 5"],
55
"license": "MIT",
66
"authors": [
77
{
@@ -28,8 +28,13 @@
2828
"component": "package",
2929
"frameworks": ["Laravel 5"],
3030
"branch-alias": {
31-
"dev-master": "0.0-dev"
32-
}
31+
"dev-master": "2.0-dev"
32+
},
33+
"laravel": {
34+
"providers": [
35+
"Understand\\UnderstandLaravel5\\UnderstandLaravel5ServiceProvider"
36+
]
37+
}
3338
},
3439
"minimum-stability": "stable"
3540
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php namespace Understand\UnderstandLaravel5;
2+
3+
class DataCollector
4+
{
5+
6+
/**
7+
* Current token
8+
*
9+
* @var type
10+
*/
11+
protected $data = [];
12+
13+
/**
14+
* @param $key
15+
* @param $value
16+
*/
17+
public function set($key, $value)
18+
{
19+
$this->data[$key] = $value;
20+
}
21+
22+
/**
23+
* @param $key
24+
* @param $value
25+
*/
26+
public function setInArray($key, $value)
27+
{
28+
$this->data[$key][] = $value;
29+
}
30+
31+
/**
32+
* @param $key
33+
* @return mixed
34+
*/
35+
public function getByKey($key)
36+
{
37+
if (isset($this->data[$key]))
38+
{
39+
return $this->data[$key];
40+
}
41+
}
42+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php namespace Understand\UnderstandLaravel5;
2+
3+
use Illuminate\Config\Repository;
4+
5+
class EventLogger
6+
{
7+
8+
/**
9+
* Log writer
10+
*
11+
* @var Logger
12+
*/
13+
protected $logger;
14+
15+
/**
16+
* Configuration
17+
*
18+
* @var array
19+
*/
20+
protected $config;
21+
22+
/**
23+
* @param Logger $logger
24+
* @param Repository $config
25+
*/
26+
public function __construct(
27+
Logger $logger,
28+
Repository $config
29+
)
30+
{
31+
$this->logger = $logger;
32+
$this->config = $config;
33+
}
34+
35+
/**
36+
* @param $level
37+
* @param $message
38+
* @param $context
39+
*/
40+
public function logEvent($level, $message, $context)
41+
{
42+
// integer, float, string or boolean as message
43+
if (is_scalar($message))
44+
{
45+
$log = [
46+
'message' => $message
47+
];
48+
}
49+
else
50+
{
51+
$log = (array)$message;
52+
}
53+
54+
$log['tags'] = ['laravel_log'];
55+
$log['level'] = $level;
56+
57+
if ($context)
58+
{
59+
$log['context'] = (array)$context;
60+
}
61+
62+
$additionalFields = $this->getMetaFields();
63+
$customFields = $this->config->get('understand-laravel.events.meta', []);
64+
65+
$this->logger->log($log, $additionalFields, $customFields);
66+
}
67+
68+
/**
69+
* @return array
70+
*/
71+
protected function getMetaFields()
72+
{
73+
return [
74+
'session_id' => 'UnderstandFieldProvider::getSessionId',
75+
'request_id' => 'UnderstandFieldProvider::getProcessIdentifier',
76+
'user_id' => 'UnderstandFieldProvider::getUserId',
77+
'env' => 'UnderstandFieldProvider::getEnvironment',
78+
'url' => 'UnderstandFieldProvider::getUrl',
79+
'method' => 'UnderstandFieldProvider::getRequestMethod',
80+
'client_ip' => 'UnderstandFieldProvider::getClientIp',
81+
];
82+
}
83+
}

src/Understand/UnderstandLaravel5/ExceptionEncoder.php

Lines changed: 165 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,39 @@
11
<?php namespace Understand\UnderstandLaravel5;
22

3+
use Exception;
4+
use Throwable;
5+
use InvalidArgumentException;
6+
use SplFileObject;
7+
38
class ExceptionEncoder
49
{
510

11+
/**
12+
* @var string
13+
*/
14+
protected $projectRoot;
15+
16+
/**
17+
* @param string $projectRoot
18+
*/
19+
public function setProjectRoot($projectRoot)
20+
{
21+
$this->projectRoot = $projectRoot;
22+
}
23+
624
/**
725
* Serialize exception object
826
*
9-
* @param \Exception $exception
10-
* @return type
27+
* @param mixed $exception
28+
* @return array
1129
*/
12-
public function exceptionToArray(\Exception $exception)
30+
public function exceptionToArray($exception)
1331
{
32+
if ( ! ($exception instanceof Exception || $exception instanceof Throwable))
33+
{
34+
throw new InvalidArgumentException('$exception must be instance of Exception or Throwable');
35+
}
36+
1437
$trace = $exception->getTrace();
1538
$className = get_class($exception);
1639
$message = $exception->getMessage() ? $exception->getMessage() : $className;
@@ -19,24 +42,103 @@ public function exceptionToArray(\Exception $exception)
1942
'message' => $message,
2043
'class' => $className,
2144
'code' => $exception->getCode(),
22-
'file' => $exception->getFile(),
45+
'file' => $this->removeProjectRoot($exception->getFile()),
2346
'line' => $exception->getLine(),
24-
'stack' => $this->stackTraceToArray($trace)
47+
'stack' => $this->stackTraceToArray($trace, $exception->getFile(), $exception->getLine())
2548
];
2649
}
2750

51+
/**
52+
* @param array $errorLog
53+
* @return array
54+
*/
55+
public function setCurrentStackTrace(array $errorLog)
56+
{
57+
$level = isset($errorLog['level']) ? $errorLog['level'] : null;
58+
$stackTrace = $this->getCurrentStackTrace($level);
59+
$firstLineSet = false;
60+
61+
foreach($stackTrace as $trace)
62+
{
63+
if ($firstLineSet)
64+
{
65+
break;
66+
}
67+
68+
$firstLineSet = true;
69+
70+
$errorLog['class'] = null;
71+
$errorLog['file'] = isset($trace['file']) ? $trace['file'] : null;
72+
$errorLog['line'] = isset($trace['line']) ? $trace['line'] : null;
73+
}
74+
75+
$errorLog['stack'] = $stackTrace;
76+
77+
return $errorLog;
78+
}
79+
80+
/**
81+
* @return array
82+
*/
83+
protected function getCurrentStackTrace()
84+
{
85+
$stackTrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 100);
86+
$vendorExcluded = false;
87+
88+
foreach($stackTrace as $index => $trace)
89+
{
90+
// exclude Understand service provider and helper classes
91+
if (isset($trace['class']) && strpos($trace['class'], 'Understand\UnderstandLaravel5\\') === 0)
92+
{
93+
unset($stackTrace[$index]);
94+
}
95+
96+
if ( ! isset($trace['file']))
97+
{
98+
$vendorExcluded = true;
99+
}
100+
101+
if ($vendorExcluded)
102+
{
103+
continue;
104+
}
105+
106+
// exclude `vendor` folder until project path reached
107+
if (strpos($trace['file'], $this->projectRoot . 'vendor' . DIRECTORY_SEPARATOR) === 0)
108+
{
109+
unset($stackTrace[$index]);
110+
}
111+
else
112+
{
113+
$vendorExcluded = true;
114+
}
115+
}
116+
117+
return $this->stackTraceToArray($stackTrace);
118+
}
119+
28120
/**
29121
* Serialize stack trace to array
30122
*
31123
* @param array $stackTrace
32124
* @return array
33125
*/
34-
public function stackTraceToArray(array $stackTrace)
126+
public function stackTraceToArray(array $stackTrace, $topFile = null, $topLine = null)
35127
{
36128
$stack = [];
37129

38130
foreach ($stackTrace as $trace)
39131
{
132+
// Exception object `getTrace` does not return file and line number for the first line
133+
// http://php.net/manual/en/exception.gettrace.php#107563
134+
if (isset($topFile, $topLine) && $topFile && $topLine)
135+
{
136+
$trace['file'] = $topFile;
137+
$trace['line'] = $topLine;
138+
139+
unset($topFile, $topLine);
140+
}
141+
40142
$type = $this->stackTraceCallToString($trace);
41143
$args = $this->stackTraceArgsToArray($trace);
42144

@@ -46,13 +148,57 @@ public function stackTraceToArray(array $stackTrace)
46148
'args' => $args,
47149
'type' => $type,
48150
'file' => $this->getStackTraceFile($trace),
49-
'line' => $this->getStackTraceLine($trace)
151+
'line' => $this->getStackTraceLine($trace),
152+
'code' => $this->getCode($this->getStackTraceFile($trace), $this->getStackTraceLine($trace)),
50153
];
51154
}
52155

53156
return $stack;
54157
}
55158

159+
/**
160+
* @param $relativePath
161+
* @param $line
162+
* @param int $linesAround
163+
* @return array|void
164+
*/
165+
public function getCode($relativePath, $line, $linesAround = 6)
166+
{
167+
if ( ! $relativePath || ! $line)
168+
{
169+
return;
170+
}
171+
172+
$filePath = $this->projectRoot . $relativePath;
173+
174+
try
175+
{
176+
$file = new SplFileObject($filePath);
177+
$file->setMaxLineLen(250);
178+
$file->seek(PHP_INT_MAX);
179+
$codeLines = [];
180+
181+
$from = max(0, $line - $linesAround - 2);
182+
$to = min($line + $linesAround -1, $file->key() + 1);
183+
184+
$file->seek($from);
185+
186+
while ($file->key() < $to && ! $file->eof())
187+
{
188+
$file->next();
189+
// `key()` returns 0 as the first line
190+
$codeLines[] = [
191+
'line' => $file->key() + 1,
192+
'code' => rtrim($file->current())
193+
];
194+
}
195+
196+
return $codeLines;
197+
}
198+
catch (\Exception $e)
199+
{}
200+
}
201+
56202
/**
57203
* Return stack trace line number
58204
*
@@ -77,7 +223,7 @@ protected function getStackTraceFile(array $trace)
77223
{
78224
if (isset($trace['file']))
79225
{
80-
return $trace['file'];
226+
return $this->removeProjectRoot($trace['file']);
81227
}
82228
}
83229

@@ -159,4 +305,15 @@ protected function stackTraceArgsToArray(array $trace)
159305
return $params;
160306
}
161307

308+
/**
309+
* @param $path
310+
* @return string
311+
*/
312+
protected function removeProjectRoot($path)
313+
{
314+
if (substr($path, 0, strlen($this->projectRoot)) == $this->projectRoot)
315+
{
316+
return substr($path, strlen($this->projectRoot));
317+
}
318+
}
162319
}

0 commit comments

Comments
 (0)