Skip to content

Commit

Permalink
create: add the handler error to manage the global exceptions and errors
Browse files Browse the repository at this point in the history
  • Loading branch information
DiegoAndresRamirez committed Dec 7, 2024
1 parent 10d1211 commit fb74e5b
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 66 deletions.
97 changes: 64 additions & 33 deletions app/Exceptions/Handler.php
Original file line number Diff line number Diff line change
@@ -1,49 +1,80 @@
<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Throwable;
use App\Helpers\DiscordNotifier;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Support\Facades\Log;

class Handler extends ExceptionHandler
{
protected $dontReport = [
\Illuminate\Validation\ValidationException::class,
\Illuminate\Session\TokenMismatchException::class,
];

/**
* Report the exception.
*
* @param \Throwable $exception
* @return void
*/
public function report(Throwable $exception)
{
// Notifica a Discord si no está en la lista de exclusión
parent::report($exception);

// Log para depuración
Log::info('Se está reportando una excepción: ' . $exception->getMessage());

// Captura excepciones personalizadas y envíalas a Discord
if ($this->shouldReport($exception)) {
try {
$this->notifyDiscord($exception);
} catch (Throwable $e) {
// Evitar que fallos en la notificación rompan el flujo
logger()->error("Error al enviar notificación a Discord: " . $e->getMessage());
}
DiscordNotifier::notifyException($exception); // Notificar a Discord
}

parent::report($exception);
// Captura errores HTTP (como 404, 500, etc.) y envíalos a Discord
if ($exception instanceof HttpException) {
// Aquí puedes poner un log adicional o realizar otra acción si es necesario.
Log::info("Capturado error HTTP: " . $exception->getStatusCode());
DiscordNotifier::notifyEvent("HTTP Error: " . $exception->getStatusCode(), [
'Status Code' => $exception->getStatusCode(),
'Error Message' => $exception->getMessage(),
'URL' => request()->url(),
'Timestamp' => now()->toDateTimeString(),
]);
}
}

protected function notifyDiscord(Throwable $exception)
{
$details = [
'message' => $exception->getMessage(),
'file' => "{$exception->getFile()}:{$exception->getLine()}",
'trace' => substr($exception->getTraceAsString(), 0, 1800),
];

// Logea el error antes de enviarlo a Discord
logger()->error('Excepción capturada', $details);

// Envía la notificación a Discord
DiscordNotifier::notifyEvent(
'Excepción en el sistema 🚨',
$details,
asset('images/logo.png')
);
}
/**
* Determine if the exception should be reported.
*
* @param \Throwable $exception
* @return bool
*/
public function shouldReport(Throwable $exception)
{
// Reportar todos los errores HTTP, incluyendo 404 y 500
if ($exception instanceof HttpException) {
return true; // Se reporta cualquier error HTTP (404, 500, etc.)
}

// Puedes agregar más excepciones personalizadas aquí si es necesario
return parent::shouldReport($exception);
}

/**
* Render the exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Throwable $exception
* @return \Illuminate\Http\Response
*/
public function render($request, Throwable $exception)
{
// Renderizar errores HTTP (como 404, 500) de forma personalizada
if ($exception instanceof HttpException) {
return response()->json([
'message' => 'Error HTTP detectado.',
'error' => $exception->getMessage(),
], $exception->getStatusCode());
}

return parent::render($request, $exception);
}
}
87 changes: 64 additions & 23 deletions app/Helpers/DiscordNotifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,93 @@
namespace App\Helpers;

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Throwable;

class DiscordNotifier
{
public static function send($message, $embed = [])
{
$webhookUrl = env('DISCORD_WEBHOOK_URL');

if ($webhookUrl) {
$payload = [
'content' => $message,
'embeds' => $embed ? [$embed] : [],
];

if (!empty($embed)) {
$payload['embeds'] = [$embed];

try {
$response = Http::post($webhookUrl, $payload);

if ($response->successful()) {
Log::info('Notificación enviada a Discord correctamente.');
} else {
Log::error('Error al enviar notificación a Discord. Código de error: ' . $response->status());
}
} catch (\Exception $e) {
Log::error('Error al intentar enviar la solicitud a Discord: ' . $e->getMessage());
}

Http::post($webhookUrl, $payload);
} else {
Log::error('La URL del Webhook de Discord no está configurada.');
}
}




public static function notifyException(\Throwable $exception)
public static function notifyException(Throwable $exception)
{
$trace = substr($exception->getTraceAsString(), 0, 1800); // Discord tiene límites.
$message = "**🚨 Exception Alert**\n"
. "**Mensaje:** {$exception->getMessage()}\n"
. "**Archivo:** {$exception->getFile()}:{$exception->getLine()}\n"
. "**Trace:** ```{$trace}```";

self::send($message);
$webhookUrl = env('DISCORD_WEBHOOK_URL');

if ($webhookUrl) {
// Construir el mensaje de la excepción
$message = "**🚨 Excepción Crítica**\n"
. "**Mensaje:** {$exception->getMessage()}\n"
. "**Archivo:** {$exception->getFile()}:{$exception->getLine()}\n"
. "**Trace:** ```" . substr($exception->getTraceAsString(), 0, 1800) . "```";

// Crear el embed para Discord
$embed = [
'title' => '🚨 Error Crítico del Sistema',
'description' => $message,
'color' => 16711680, // Rojo para alertas
'footer' => [
'text' => 'Notificaciones de Excepciones',
'icon_url' => asset('images/logo.png'), // Asegúrate de que esta URL sea válida
],
'timestamp' => now()->toIso8601String(),
];

// Enviar el embed a Discord
self::send('', $embed);
}
}






public static function notifyEvent($eventType, $details = [], $imageUrl = null)
{
$webhookUrl = env('DISCORD_WEBHOOK_URL');

if ($webhookUrl) {
$logoUrl = $imageUrl ?? asset('logo.png'); // Imagen por defecto
$logoUrl = $imageUrl ?? asset('https://gananza.crudzaso.com/assets/media/auth/agency-dark.png'); // Imagen por defecto
$embed = [
'title' => '🔔 Notificación del Sistema',
'description' => "Se ha detectado un evento: **{$eventType}**.",
'color' => 7506394, // Color (hex: #72A0C1)
'title' => "🔔 {$eventType}",
'description' => "Un nuevo evento ha sido detectado: **{$eventType}**.",
'color' => 7506394,
'fields' => [],
'footer' => [
'text' => 'Notificaciones del Sistema',
'text' => 'Sistema de Notificaciones',
'icon_url' => $logoUrl,
],
'timestamp' => now()->toIso8601String(),
'thumbnail' => [
'url' => $logoUrl,
],
];

// Agregar detalles al mensaje.

foreach ($details as $key => $value) {
$embed['fields'][] = [
'name' => ucfirst($key),
Expand All @@ -61,7 +98,11 @@ public static function notifyEvent($eventType, $details = [], $imageUrl = null)
];
}



// Enviar el mensaje a Discord
self::send('', $embed);
}
}

}
8 changes: 6 additions & 2 deletions app/Http/Middleware/HandleExceptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Closure;
use Throwable;
use App\Helpers\DiscordNotifier;
use Illuminate\Support\Facades\Log;

class HandleExceptions
{
Expand All @@ -14,17 +15,20 @@ public function handle($request, Closure $next)
return $next($request);
} catch (Throwable $e) {
$this->reportToDiscord($e); // Enviar notificación a Discord
throw $e; // Rethrow para permitir que el sistema maneje la excepción
throw $e; // Volver a lanzar la excepción para que el sistema maneje la excepción
}
}

protected function reportToDiscord(Throwable $exception)
{

Log::info('Enviando excepción a Discord: ' . $exception->getMessage());

$message = "**🚨 Excepción Crítica**\n"
. "**Mensaje:** {$exception->getMessage()}\n"
. "**Archivo:** {$exception->getFile()}:{$exception->getLine()}\n"
. "**Trace:** ```" . substr($exception->getTraceAsString(), 0, 1800) . "```";

DiscordNotifier::send($message);
DiscordNotifier::send($message); // Enviar a Discord
}
}
24 changes: 18 additions & 6 deletions app/Listeners/SendLoginNotification.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,32 @@

use Illuminate\Auth\Events\Login;
use App\Helpers\DiscordNotifier;
use Illuminate\Auth\Events\Logout;

class SendLoginNotification
{
/**
* Handle the event.
*
* @param Login $event
* @param mixed $event
* @return void
*/
public function handle(Login $event)
public function handle($event)
{
DiscordNotifier::notifyEvent('User Logged In', [
'user_id' => $event->user->id,
'email' => $event->user->email,
]);
if ($event instanceof Login) {
DiscordNotifier::notifyEvent('User Logged In', [
'User ID' => $event->user->id,
'Email' => $event->user->email,
'Login Time' => now()->toDateTimeString(),
], 'https://cdn0.iconfinder.com/data/icons/very-basic-android-l-lollipop-icon-pack/24/key-256.png');
}

if ($event instanceof Logout) {
DiscordNotifier::notifyEvent('User Logged Out', [
'User ID' => $event->user->id,
'Email' => $event->user->email,
'Logout Time' => now()->toDateTimeString(),
], 'https://cdn3.iconfinder.com/data/icons/remixicon-system/24/login-box-line-256.png');
}
}
}
7 changes: 7 additions & 0 deletions app/Providers/EventServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

namespace App\Providers;

use App\Listeners\SendHttpErrorNotification;
use Illuminate\Auth\Events\Login;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use App\Listeners\SendLoginNotification;
use Illuminate\Auth\Events\Logout;
use Symfony\Component\HttpKernel\Exception\HttpException;

class EventServiceProvider extends ServiceProvider
{
Expand All @@ -17,8 +20,12 @@ class EventServiceProvider extends ServiceProvider
Login::class => [
SendLoginNotification::class,
],
Logout::class => [
SendLoginNotification::class,
],
];


/**
* Register any events for your application.
*
Expand Down
10 changes: 8 additions & 2 deletions bootstrap/app.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<?php

use App\Helpers\DiscordNotifier;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Support\Facades\Log;

return Application::configure(basePath: dirname(__DIR__))
->withRouting(
Expand All @@ -27,5 +29,9 @@
]);
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();
// Captura todas las excepciones reportables y envíalas a Discord
$exceptions->report(function (Throwable $exception) {
Log::info('Excepción reportada: ' . $exception->getMessage()); // Log de depuración
DiscordNotifier::notifyException($exception); // Reportar la excepción a Discord
});
})->create();
7 changes: 7 additions & 0 deletions routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,10 @@
Route::post('/verify-payment', [PaymentVerificationController::class, 'verifyPayment']);


Route::get('/test-404', function () {
abort(404);
});

Route::get('/test-500', function () {
abort(500);
});

0 comments on commit fb74e5b

Please sign in to comment.