Compare commits
12
Commits
1.0.0
...
72e50fbe50
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72e50fbe50 | ||
|
|
27bfdd5902 | ||
|
|
063aba6040 | ||
|
|
956ccbba1a | ||
|
|
af0e9f291d | ||
|
|
bc8d831b6c | ||
|
|
2df4ea15e2 | ||
|
|
0694b50eb6 | ||
|
|
72f5341dff | ||
|
|
b88602a98b | ||
|
|
f1e9dddf5e | ||
|
|
8de8aafa84 |
No files matched your search
+64
-40
@@ -9,36 +9,6 @@ class ErrorHandler {
|
|||||||
this.catchError();
|
this.catchError();
|
||||||
}
|
}
|
||||||
|
|
||||||
getSourceCode(lineNumber) {
|
|
||||||
return this.getInlineSourceCode(lineNumber) || this.getFullSourceWithHighlight(lineNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
getInlineSourceCode(lineNumber) {
|
|
||||||
const scripts = document.querySelectorAll('script');
|
|
||||||
for (let script of scripts) {
|
|
||||||
if (!script.src) {
|
|
||||||
const scriptLines = script.textContent.split("\n");
|
|
||||||
const scriptPosition = this.getErrorPosition(script);
|
|
||||||
if (lineNumber >= scriptPosition.startLine && lineNumber <= scriptPosition.endLine) {
|
|
||||||
return this.highlightSource(scriptLines, lineNumber - scriptPosition.startLine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
getFullSourceWithHighlight(lineNumber) {
|
|
||||||
const lines = document.documentElement.outerHTML.split("\n");
|
|
||||||
return this.highlightSource(lines, lineNumber - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
highlightSource(lines, lineNumber) {
|
|
||||||
const start = Math.max(lineNumber - 2, 0);
|
|
||||||
const end = Math.min(lineNumber + 2, lines.length - 1);
|
|
||||||
lines[lineNumber] = '>> ' + lines[lineNumber] + ' <<';
|
|
||||||
return lines.slice(start, end + 1).join("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
getErrorPosition(script) {
|
getErrorPosition(script) {
|
||||||
let totalLines = 0;
|
let totalLines = 0;
|
||||||
let element = script.previousElementSibling;
|
let element = script.previousElementSibling;
|
||||||
@@ -54,18 +24,32 @@ class ErrorHandler {
|
|||||||
|
|
||||||
catchError() {
|
catchError() {
|
||||||
window.onerror = (message, url, lineNumber, column, error) => {
|
window.onerror = (message, url, lineNumber, column, error) => {
|
||||||
this.reportError(message, url, lineNumber, column, error.stack, 'JavaScript Error');
|
let type = 'JavaScript Error';
|
||||||
|
|
||||||
|
if (message.indexOf(':')) {
|
||||||
|
type = message.substring(0, message.indexOf(':'));
|
||||||
|
message = message.substring(message.indexOf(':') + 1).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.reportError(message, url, lineNumber, column, error.stack, type);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener('unhandledrejection', event => {
|
window.addEventListener('unhandledrejection', event => {
|
||||||
this.reportError(event.reason.toString(), document.location.href, 0, 0, event.reason.stack, 'Promise Rejection');
|
this.reportError(event.reason.toString(), document.location.href, 0, 0, event.reason.stack, 'Promise Rejection');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this.createErrorAgain();
|
||||||
}
|
}
|
||||||
|
|
||||||
reportError(message, url, lineNumber, column, stack, type = 'JavaScript Error') {
|
async reportError(message, url, line, column, stack, type = 'JavaScript Error') {
|
||||||
fetch(this.url ? `${location.protocol}//${this.url}/${this.apikey}` : window.location.href, {
|
await new Promise(r => setTimeout(r, 2000));
|
||||||
method: "post",
|
|
||||||
|
fetch(this.url ? `${this.url}/${this.apikey}` : window.location.href, {
|
||||||
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': "application/json",
|
'Accept': "application/json",
|
||||||
'Content-Type': "application/json"
|
'Content-Type': "application/json"
|
||||||
@@ -74,12 +58,52 @@ class ErrorHandler {
|
|||||||
type,
|
type,
|
||||||
message,
|
message,
|
||||||
url,
|
url,
|
||||||
lineNumber,
|
line,
|
||||||
column,
|
code: column,
|
||||||
stack,
|
backtrace: stack ? stack.split("\n").filter((e) => !!e).map((e) => this.parseErrorLine(e)) : [],
|
||||||
location: window.location.href,
|
file: window.location.href,
|
||||||
source: this.getSourceCode(lineNumber)
|
source: await this.getSourceCode(url, line),
|
||||||
})
|
})
|
||||||
}).then(response => response.json()).then(console.info);
|
}).then(response => response.json()).then(console.info);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
async getSourceCode(url, errorLineNumber) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(url);
|
||||||
|
const originalHtml = await response.text();
|
||||||
|
const lines = originalHtml.split('\n');
|
||||||
|
|
||||||
|
const start = Math.max(0, errorLineNumber - 5);
|
||||||
|
const end = Math.min(lines.length, errorLineNumber + 5);
|
||||||
|
|
||||||
|
return lines.slice(start, end).join('\n');
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error('Failed to fetch original HTML:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parseErrorLine(errorLine) {
|
||||||
|
const obj = {};
|
||||||
|
|
||||||
|
// Pattern for: functionName@url:line:column
|
||||||
|
const pattern = /^(.*)@(.+?):(\d+):(\d+)$/;
|
||||||
|
const match = errorLine.match(pattern);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
obj.function = match[1];
|
||||||
|
obj.file = match[2];
|
||||||
|
obj.line = match[3];
|
||||||
|
// column would be match[4] if needed
|
||||||
|
|
||||||
|
console.log(match);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove undefined/empty values
|
||||||
|
Object.keys(obj).forEach(key => {
|
||||||
|
if (!obj[key]) delete obj[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
-3
@@ -1,15 +1,33 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use function DI\autowire, DI\create, DI\get;
|
|
||||||
|
|
||||||
use Negundo\Client\{ SoftwareConfig, Dump, Task, NegundoMiddleware };
|
use Negundo\Client\{ SoftwareConfig, Dump, Task, NegundoMiddleware };
|
||||||
|
|
||||||
|
use function DI\{ autowire, create, get, add };
|
||||||
|
|
||||||
|
if (! function_exists('getenvonce')) {
|
||||||
|
function getenvonce(string $name) : array|string|false
|
||||||
|
{
|
||||||
|
$value = getenv($name);
|
||||||
|
unset($_ENV[$name], $_SERVER[$name]);
|
||||||
|
putenv($name . "=");
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
SoftwareConfig::class => create(SoftwareConfig::class)->constructor(getenv('NEGUNDO_HASH'), getenv('NEGUNDO_SERVER')),
|
SoftwareConfig::class => create(SoftwareConfig::class)->constructor(
|
||||||
|
serverUrl: getenvonce('NEGUNDO_SERVER'),
|
||||||
|
softwareHash: getenvonce('NEGUNDO_HASH'),
|
||||||
|
),
|
||||||
NegundoMiddleware::class => autowire(NegundoMiddleware::class),
|
NegundoMiddleware::class => autowire(NegundoMiddleware::class),
|
||||||
Dump::class => autowire(Dump::class),
|
Dump::class => autowire(Dump::class),
|
||||||
Task::class => autowire(Task::class),
|
Task::class => autowire(Task::class),
|
||||||
|
|
||||||
|
'lean.autoload' => add([
|
||||||
|
Dump::class,
|
||||||
|
Task::class,
|
||||||
|
]),
|
||||||
|
|
||||||
'negundo.client' => [
|
'negundo.client' => [
|
||||||
'picea' => [
|
'picea' => [
|
||||||
'asset' => [
|
'asset' => [
|
||||||
|
|||||||
+4
-2
@@ -14,7 +14,7 @@ namespace Negundo\Client {
|
|||||||
|
|
||||||
protected Util\DumpHandler $dumpHandler;
|
protected Util\DumpHandler $dumpHandler;
|
||||||
|
|
||||||
public function __construct(SoftwareConfig $config, ? DataInterface $dataManipulator = null, Transport\TransportInterface $transport = null)
|
public function __construct(SoftwareConfig $config, ? DataInterface $dataManipulator = null, ? Transport\TransportInterface $transport = null)
|
||||||
{
|
{
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
$this->transport = $transport ?: new Transport\Curl();
|
$this->transport = $transport ?: new Transport\Curl();
|
||||||
@@ -35,7 +35,9 @@ namespace Negundo\Client {
|
|||||||
|
|
||||||
$this->sent[$dumpHash] = true;
|
$this->sent[$dumpHash] = true;
|
||||||
|
|
||||||
return $this->transport->push($this->config->url('dump/report'), $data);
|
$url = $this->config->url('dump/report');
|
||||||
|
|
||||||
|
return $url ? $this->transport->push($url, $data) : false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -23,7 +23,7 @@ abstract class Handler {
|
|||||||
|
|
||||||
public abstract function handleException(\Throwable $ex) : array;
|
public abstract function handleException(\Throwable $ex) : array;
|
||||||
|
|
||||||
public function __construct(SoftwareConfig $config, ? DataInterface $dataManipulator = null, ? Closure $callback = null, Transport\TransportInterface $transport = null)
|
public function __construct(SoftwareConfig $config, ? DataInterface $dataManipulator = null, ? Closure $callback = null, ? Transport\TransportInterface $transport = null)
|
||||||
{
|
{
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
|
|
||||||
@@ -68,6 +68,8 @@ abstract class Handler {
|
|||||||
|
|
||||||
$data = $this->handleException($ex);
|
$data = $this->handleException($ex);
|
||||||
|
|
||||||
return $this->transport->push($this->config->url('bug/report'), $data);
|
$url = $this->config->url('bug/report');
|
||||||
|
|
||||||
|
return $url ? $this->transport->push($url, $data) : false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-19
@@ -4,29 +4,17 @@ namespace Negundo\Client;
|
|||||||
|
|
||||||
class SoftwareConfig
|
class SoftwareConfig
|
||||||
{
|
{
|
||||||
public string $serverUrl;
|
public function __construct(
|
||||||
|
public string $serverUrl,
|
||||||
|
public string $softwareHash,
|
||||||
|
) {}
|
||||||
|
|
||||||
public string $softwareHash;
|
public function url(string $path) : string|null
|
||||||
|
|
||||||
public function __construct(string $softwareHash, string $serverUrl)
|
|
||||||
{
|
{
|
||||||
if (! $softwareHash ) {
|
if (empty($this->serverUrl) || empty($this->softwareHash)) {
|
||||||
throw new \Exception("[Negundo] - You must provide a software hash to match a registered application on the plateform.");
|
return null;
|
||||||
}
|
|
||||||
else {
|
|
||||||
$this->softwareHash = $softwareHash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! $serverUrl ) {
|
|
||||||
throw new \Exception("[Negundo] - You must provide a valid Negundo server url endpoint.");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$this->serverUrl = $serverUrl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function url(string $path) : string
|
|
||||||
{
|
|
||||||
return sprintf("%s/%s/%s", rtrim($this->serverUrl, '/'), $path, $this->softwareHash);
|
return sprintf("%s/%s/%s", rtrim($this->serverUrl, '/'), $path, $this->softwareHash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+4
-4
@@ -14,7 +14,7 @@ namespace Negundo\Client {
|
|||||||
|
|
||||||
protected SoftwareConfig $config;
|
protected SoftwareConfig $config;
|
||||||
|
|
||||||
public function __construct(SoftwareConfig $config, ? DataInterface $dataManipulator = null, Transport\TransportInterface $transport = null)
|
public function __construct(SoftwareConfig $config, ? DataInterface $dataManipulator = null, ? Transport\TransportInterface $transport = null)
|
||||||
{
|
{
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
|
|
||||||
@@ -30,13 +30,13 @@ namespace Negundo\Client {
|
|||||||
$report = $this->taskHandler->sendReport($message, $title, $data, $events);
|
$report = $this->taskHandler->sendReport($message, $title, $data, $events);
|
||||||
|
|
||||||
// Make sure not to spam the server if an ErrorMessage or Exception was already sent (like inside a loop)
|
// Make sure not to spam the server if an ErrorMessage or Exception was already sent (like inside a loop)
|
||||||
$dumpHash = $this->taskHandler->hash($report);
|
$taskHash = $this->taskHandler->hash($report);
|
||||||
|
|
||||||
if ( $this->sent[$dumpHash] ?? false ) {
|
if ( $this->sent[$taskHash] ?? false ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->sent[$dumpHash] = true;
|
$this->sent[$taskHash] = true;
|
||||||
|
|
||||||
return $this->transport->push($this->config->url('task/report'), $report);
|
return $this->transport->push($this->config->url('task/report'), $report);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace Negundo\Client\Task;
|
|||||||
|
|
||||||
enum StatusEnum : string
|
enum StatusEnum : string
|
||||||
{
|
{
|
||||||
|
case New = "new";
|
||||||
case Failed = "failed";
|
case Failed = "failed";
|
||||||
case Warning = "warning";
|
case Warning = "warning";
|
||||||
case Completed = "completed";
|
case Completed = "completed";
|
||||||
|
|||||||
+15
-3
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Negundo\Client\Task;
|
namespace Negundo\Client\Task;
|
||||||
|
|
||||||
class TaskReport
|
class TaskReport implements \JsonSerializable
|
||||||
{
|
{
|
||||||
protected array $events = [];
|
protected array $events = [];
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@ class TaskReport
|
|||||||
public array $data = [],
|
public array $data = [],
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|
||||||
public function addData(string $name, array $data) : static
|
public function addData(string $name, array $data) : static
|
||||||
{
|
{
|
||||||
$this->data[$name][] = $data;
|
$this->data[$name][] = $data;
|
||||||
@@ -60,13 +61,24 @@ class TaskReport
|
|||||||
return $this->data;
|
return $this->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getEvents() : array
|
public function getEvents(?StatusEnum $filterType = null) : array
|
||||||
{
|
{
|
||||||
return $this->events;
|
return $filterType ? array_filter($this->events, fn($e) => StatusEnum::tryFrom($e['status']) === $filterType) : $this->events;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStatus() : StatusEnum
|
public function getStatus() : StatusEnum
|
||||||
{
|
{
|
||||||
return $this->status;
|
return $this->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function jsonSerialize(): mixed
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'title' => $this->getTitle(),
|
||||||
|
'message' => $this->getMessage(),
|
||||||
|
'status' => $this->getStatus(),
|
||||||
|
'events' => $this->getEvents(),
|
||||||
|
'data' => $this->getData(),
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+3
-14
@@ -4,7 +4,7 @@ namespace Negundo\Client\Transport;
|
|||||||
|
|
||||||
class Curl implements TransportInterface {
|
class Curl implements TransportInterface {
|
||||||
|
|
||||||
public $timeout = 100;
|
public $timeout = 4;
|
||||||
|
|
||||||
public $throwErrors = true;
|
public $throwErrors = true;
|
||||||
|
|
||||||
@@ -15,13 +15,13 @@ class Curl implements TransportInterface {
|
|||||||
public function push(string $url, array $data) : object|null|bool
|
public function push(string $url, array $data) : object|null|bool
|
||||||
{
|
{
|
||||||
$ch = curl_init();
|
$ch = curl_init();
|
||||||
|
|
||||||
curl_setopt($ch, CURLOPT_URL, $url);
|
curl_setopt($ch, CURLOPT_URL, $url);
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers );
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers );
|
||||||
curl_setopt($ch, CURLOPT_POST, 1);
|
curl_setopt($ch, CURLOPT_POST, 1);
|
||||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data, '', '&'));
|
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data, '', '&'));
|
||||||
curl_setopt($ch, CURLOPT_TIMEOUT_MS, $this->timeout * 200);
|
curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
|
||||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->verifySsl);
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->verifySsl);
|
||||||
|
|
||||||
$exec = curl_exec($ch);
|
$exec = curl_exec($ch);
|
||||||
@@ -31,19 +31,12 @@ class Curl implements TransportInterface {
|
|||||||
if ($this->throwErrors) {
|
if ($this->throwErrors) {
|
||||||
if ( false === $exec) {
|
if ( false === $exec) {
|
||||||
$errno = curl_errno($ch);
|
$errno = curl_errno($ch);
|
||||||
curl_close($ch);
|
|
||||||
|
|
||||||
throw new CurlException(implode(PHP_EOL, array_filter([ curl_error($ch) , static::CURL_ERROR[$errno] ?? null ])), $errno);
|
throw new CurlException(implode(PHP_EOL, array_filter([ curl_error($ch) , static::CURL_ERROR[$errno] ?? null ])), $errno);
|
||||||
}
|
}
|
||||||
elseif ($code >= 400) {
|
elseif ($code >= 400) {
|
||||||
throw new \Exception(sprintf("HTTP code received : $code with page content : %s", $exec));
|
throw new \Exception(sprintf("HTTP code received : $code with page content : %s", $exec));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($_GET['dev'] ?? false) {
|
|
||||||
echo($exec);
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
curl_close($ch);
|
|
||||||
|
|
||||||
return $exec;
|
return $exec;
|
||||||
}
|
}
|
||||||
@@ -62,12 +55,8 @@ class Curl implements TransportInterface {
|
|||||||
if ( ( false === $execute ) && $this->throwErrors ) {
|
if ( ( false === $execute ) && $this->throwErrors ) {
|
||||||
$errno = curl_errno($ch);
|
$errno = curl_errno($ch);
|
||||||
|
|
||||||
curl_close($ch);
|
|
||||||
throw new CurlException(implode(PHP_EOL, array_filter([ curl_error($ch) , static::CURL_ERROR[$errno] ?? null ])), $errno);
|
throw new CurlException(implode(PHP_EOL, array_filter([ curl_error($ch) , static::CURL_ERROR[$errno] ?? null ])), $errno);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
curl_close($ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $execute ? (object) $execute : null;
|
return $execute ? (object) $execute : null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,10 @@ namespace Negundo\Client\Util;
|
|||||||
use Negundo\Client\DataInterface;
|
use Negundo\Client\DataInterface;
|
||||||
|
|
||||||
class DumpHandler {
|
class DumpHandler {
|
||||||
|
|
||||||
public ? DataInterface $dataManipulator;
|
public function __construct(
|
||||||
|
public ? DataInterface $dataManipulator = null
|
||||||
public function __construct(DataInterface $dataManipulator = null)
|
) {}
|
||||||
{
|
|
||||||
$this->dataManipulator = $dataManipulator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dumpData(...$content) : array
|
public function dumpData(...$content) : array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,12 +6,9 @@ use Negundo\Client\DataInterface;
|
|||||||
|
|
||||||
class ExceptionHandler {
|
class ExceptionHandler {
|
||||||
|
|
||||||
public ? DataInterface $dataManipulator;
|
public function __construct(
|
||||||
|
public ? DataInterface $dataManipulator = null
|
||||||
public function __construct(DataInterface $dataManipulator = null)
|
) {}
|
||||||
{
|
|
||||||
$this->dataManipulator = $dataManipulator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function extractExceptionData(\Throwable $ex, array $serverData, array $postData, $dataManipulator = null) : array
|
public function extractExceptionData(\Throwable $ex, array $serverData, array $postData, $dataManipulator = null) : array
|
||||||
{
|
{
|
||||||
@@ -20,7 +17,7 @@ class ExceptionHandler {
|
|||||||
'HTTP_HOST' => $serverData['HTTP_HOST'] ?? "",
|
'HTTP_HOST' => $serverData['HTTP_HOST'] ?? "",
|
||||||
'REQUEST_URI' => $serverData['REQUEST_URI'] ?? "",
|
'REQUEST_URI' => $serverData['REQUEST_URI'] ?? "",
|
||||||
'HTTP_USER_AGENT' => $serverData['HTTP_USER_AGENT'] ?? "# UNKNOWN #",
|
'HTTP_USER_AGENT' => $serverData['HTTP_USER_AGENT'] ?? "# UNKNOWN #",
|
||||||
'REMOTE_ADDR' => $serverData['REMOTE_ADDR'] ?? null,
|
'REMOTE_ADDR' => $server['HTTP_X_FORWARDED_FOR'] ?? $serverData['REMOTE_ADDR'] ?? null,
|
||||||
'REQUEST_METHOD' => $serverData['HTTP_X_HTTP_METHOD'] ?? $serverData['REQUEST_METHOD'] ?? null,
|
'REQUEST_METHOD' => $serverData['HTTP_X_HTTP_METHOD'] ?? $serverData['REQUEST_METHOD'] ?? null,
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -31,7 +28,7 @@ class ExceptionHandler {
|
|||||||
'type' => $ex::class,
|
'type' => $ex::class,
|
||||||
'message' => $ex->getMessage(),
|
'message' => $ex->getMessage(),
|
||||||
'url' => ( ( 'on' === $serverData['HTTPS'] ) ? 'https' : 'http' ) . '://' . $serverData['HTTP_HOST'] . $serverData["REQUEST_URI"],
|
'url' => ( ( 'on' === $serverData['HTTPS'] ) ? 'https' : 'http' ) . '://' . $serverData['HTTP_HOST'] . $serverData["REQUEST_URI"],
|
||||||
'http_method' => $serverData['REQUEST_METHOD'],
|
'http_method' => strtolower($serverData['REQUEST_METHOD']),
|
||||||
'backtrace' => json_encode($ex->getTrace()),
|
'backtrace' => json_encode($ex->getTrace()),
|
||||||
'backtrace_string' => $ex->getTraceAsString(),
|
'backtrace_string' => $ex->getTraceAsString(),
|
||||||
'source' => ( new SourceCodeFormatter() )->generateFromException($ex),
|
'source' => ( new SourceCodeFormatter() )->generateFromException($ex),
|
||||||
|
|||||||
@@ -41,10 +41,9 @@ class SourceCodeFormatter {
|
|||||||
catch(\Throwable $e) {
|
catch(\Throwable $e) {
|
||||||
$content = $fileSpl->current();
|
$content = $fileSpl->current();
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get code between <code></code> tags
|
$content = strip_tags($content, '<span>');
|
||||||
$content = substr($content, strpos($content, "<code>") + 6, strrpos($content, "</code>") - 6);
|
|
||||||
|
|
||||||
# Removing the added <?php tag
|
# Removing the added <?php tag
|
||||||
$content = str_replace("<?php", "", $content);
|
$content = str_replace("<?php", "", $content);
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,9 @@ use Negundo\Client\DataInterface;
|
|||||||
|
|
||||||
class TaskHandler {
|
class TaskHandler {
|
||||||
|
|
||||||
public ? DataInterface $dataManipulator;
|
public function __construct(
|
||||||
|
public ? DataInterface $dataManipulator = null
|
||||||
public function __construct(DataInterface $dataManipulator = null)
|
) {}
|
||||||
{
|
|
||||||
$this->dataManipulator = $dataManipulator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function sendReport(string $message, ? string $title = null, array $data = [], array $events = []) : array
|
public function sendReport(string $message, ? string $title = null, array $data = [], array $events = []) : array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
|
{% php $softwareConfig = di_get(\Negundo\Client\SoftwareConfig::class) %}
|
||||||
|
|
||||||
<script src="{% asset 'static/negundo/js/debug.js' %}"></script>
|
<script src="{% asset 'static/negundo/js/debug.js' %}"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
new ErrorHandler({
|
new ErrorHandler({
|
||||||
url: "{{ getenv('NEGUNDO_SERVER') }}/bug/client/report",
|
url: "{{ rtrim($softwareConfig->serverUrl, '/') }}/bug/client/report",
|
||||||
apikey: "{{ getenv('NEGUNDO_HASH') }}"
|
apikey: "{{ $softwareConfig->softwareHash }}"
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
Reference in new issue
Block a user