*/ class Utils { /** * Manually send an exception to team instead of going trough the error handler * (requires package kwaadpepper/exception-handler) * * @param \Throwable $e * @return void */ public static function sendEmailErrorManually(\Throwable $e) { Mail::send([ 'html' => 'exception-handler.exception', 'text' => 'exception-handler.exception-plain' ], [ 'appName' => config('app.name'), 'code' => $e->getCode(), 'line' => $e->getLine(), 'ename' => \get_class($e), 'emessage' => self::getAnonymizedMessage($e->getMessage()), 'file' => str_replace(\realpath(\sprintf('%s/../', \app_path())), '', $e->getFile()), 'stackTrace' => self::getAnonymizedStackTrace($e), 'uri' => app()->runningInConsole() ? 'CONSOLE' : ( (request() and request()->fullUrl()) ? request()->fullUrl() : 'none') ], function ($m) { /** @var \Illuminate\Mail\Message $m */ $m->to( config('mail.contactsList.serviceweb'), sprintf('%s Exception Handler', config('app.name')) )->subject('Need help !, an error occured in your application, please check Logs ASAP'); }); Log::alert(sprintf('Envoie d\'une erreur par mail : %s', json_encode($e))); } /** * Anonymize at least Sql queries * * @param string $message * @return string */ private static function getAnonymizedMessage(string $message): string { $message = \preg_replace('/^(.*)( \(SQL:.*\))$/', '$1', $message) ?? $message; return $message; } /** * Anonymize stack trace * * @param \Exception $e * @return string */ private static function getAnonymizedStackTrace(\Throwable $e): string { $projectPath = \realpath(\sprintf('%s/../', \app_path())); $traceStack = $e->getTrace(); $traceStr = ''; $maxStackStage = 0; foreach ($traceStack as $stackStage => $stack) { $maxStackStage = $stackStage; $traceStr .= \sprintf( '#%s %s(%d): ', $stackStage, str_replace($projectPath, '', $stack['file'] ?? ''), $stack['line'] ?? '' ); if (isset($stack['class'])) { $traceStr .= "{$stack['class']}->{$stack['function']}("; if (isset($stack['args'])) { $traceStr .= self::handleArgs($stack); } $traceStr .= ")\n"; } elseif (isset($stack['function'])) { $traceStr .= "{$stack['function']}("; if (isset($stack['args'])) { $traceStr .= self::handleArgs($stack); } $traceStr .= ")\n"; } } $maxStackStage++; $traceStr .= "#$maxStackStage {main}"; return $traceStr; } /** * Handle Args * * @param array $stack * @return string */ private static function handleArgs(array $stack): string { $traceArgs = ''; $argsCount = count($stack['args']); for ($i = 0; $i < $argsCount; $i++) { $type = \gettype($stack['args'][$i]); switch ($type) { case 'object': $traceArgs .= sprintf('Object(%s)', \get_class($stack['args'][$i])); break; case 'array': $traceArgs .= sprintf('Array(%d)', \count($stack['args'][$i])); break; case 'string': $traceArgs .= sprintf('String(%d)', \strlen($stack['args'][$i])); break; default: $traceArgs .= \gettype($stack['args'][$i]); } $traceArgs .= ($i !== ($argsCount - 1) ? ',' : ''); } return $traceArgs; } }