Laravel DB Max Connections error throws twice in single GET request - php

i have a proyect in production made with Laravel 5.4 on AWS, with EC2 and RDS (with autoscaling).
In a normal day our current configuration doesn't have a problem handling a certain amount of users, but sometimes this number of user grows up enough to start generating this DB Max Connections error [1040], even tho we have autoscaling configured to avoid this (i think that the replica is taking enough time to start while we still have some users trying to access).
So, in the Handler.php file we put this code to show a custom page informing the issue to the user (and not just the generic woops!)
if ($e instanceof \PDOException) {
Log::error('Data Base Exception');
$errCode = $e->getCode();
switch ($errCode) {
case 1040:
return response()->view("errors.database", []);
break;
default:
return response()->view("errors.500", [], 500);
break;
}
}
The problem is that apparently laravel is opening more than 1 connection at the same time even this is only a single GET request (it happens to any request on the proyect), so the Handler.php is reporting it twice. Here is a look at the log file generated when throwing this exception.
[2018-10-11 14:04:09] production.ERROR: Data Base Exception
[2018-10-11 14:04:09] production.ERROR: Data Base Exception
I have tested this on my local enviroment, setting the max_connections attribute from mysql to 1
set global max_connections = 1;
This throws the exception as intented, but the HTML page with the information of the problem appears also twice, just like the log.
html with error to the user
Curious thing: when i set the max_connections atributte to 2, the exception is not throwed and laravel process the request normally.
EDIT: it works in this case because i didn't considered that i was using DBeaver to access the database. But the problem of throwing the exception twice persist
The question is: what is laravel doing that need 2 conections even when is just 1 user trying to access? Or maybe this is something related with some kind of reconnection attempt?

Related

Return 500 from Laravel 7 to Google Cloud Task without abort()

In order for Google Cloud Tasks to automatically be re-queued I need my Laravel 7 app to return a 500 error, but everything short of a call to abort() seems to want to return a 200. I know that this ought to work:
return response('No dice son, you gotta work-a late.', 500);
...but no, the task still receives 200 and thus it's deleted from the queue as though it had succeeded.
The reason I'd prefer to avoid abort('Fall down go boom') is that it also raises an exception in Stackdriver, and that's unnecessary since I'm returning this particular error when a third party's API fails to provide data. In the event of errors on my side I'm killing the job outright.
The flow of my code is that I raise a custom exception when the third-party API returns null, then catch that exception and in the handler I call another method that does the work of cleaning up the job, which is when I intended to return 500... though right now I'm calling abort('No worky').
Is there some minutia in the docs that I managed to overlook?
In order to send HTTP 500, this usually would be:
return abort(500, 'Internal Server Error');
And the method usally doesn't matter, as it is just a helper, which returns Response.
Changing the error message does not chenge the fact that it's an intenral server error - and when returning 500, it is probably normal to have it logged as an error.

Laravel stops executing when an Exception occurred and displaying the message using some default template - Handling exceptions in laravel

I am using latest version laravel(5.6)
Now in my code whenever an exception occurs laravel treating it as a fatal error, stop executing instantly and displaying the error message in some template.
But I don't want that, I want to handle exceptions and display some custom error messages
I found some ways like
changing the APP_DEBUG value in the .env file to false. But this also displays another
page with the message "whoops!some this want wrong";
In Handler.php which is in app/Exceptions, I had put some exceptions in not report zone. But the app is still reporting them
Custom HTTP Error Pages
Laravel makes it easy to display custom error pages for various HTTP
status codes. For example, if you wish to customize the error page for
404 HTTP status codes, create a resources/views/errors/404.blade.php.
This file will be served on all 404 errors generated by your
application. The views within this directory should be named to match
the HTTP status code they correspond to. The HttpException instance
raised by the abort function will be passed to the view as an
$exception variable.
https://laravel.com/docs/5.6/errors#custom-http-error-pages
Really you want to be handling your exceptions. Wrap the code in a try catch and you can do all manner of things (e.g. email / slack / log). Once you have handled the exception you can still use custom http error pages inside the catch so the end user get's a friendly message on a nicely designed page. There is even a report helper built in to allow you to externally log and continue on processing the code.
#Devon's above answer re: Custom HTTP Error Pages gets you exactly what you want also.
Please note few important points :
The App\Exceptions\Handler class is where all exceptions triggered by your application are logged and then rendered back to the user. This class has two method report() and render(), both has their own responsibility.
The report method is used to log exceptions. By default, the report method passes the exception to the base class where the exception is logged. However, you are free to log exceptions however you wish. For example, if you need to report different types of exceptions in different ways, you may use the PHP instanceof comparison operator
The render method is responsible for converting a given exception into an HTTP response that should be sent back to the browser. By default, the exception is passed to the base class which generates a response for you. However, you are free to check the exception type or return your own custom response.
As in your case you want to return custom message for exception, inside render() you may use the PHP instanceof comparison operator and return you own logic.
Example :
if($exception instanceof PostTooLargeException || $exception instanceof FileException){
return response()->json([
'error' => true,
'error_message' => "The file you are trying to upload exceeds the maximum limit. Please try to upload a smaller file."
],200);
}
Go through https://laravel.com/docs/5.6/errors for more datails

Symfony 3 exceptions without error 500

Is possible in symfony 3 to generate exception without internal server error?
I want do something action with this exception (add to databases) but do not stop execute application.
I assume what you want to do is not simply catch an exception, but handle (in your case: log) an uncatched exception.
This is a common scenario and is therefore explained in the cookbook. Basically, you create an event listener class which you register as a service for the “kernel.event_listener” event.
I was struggling with this as well because I was generating custom built exceptions, but no matter what I did Symfony would return an http status of 500. I was handling errors in a controlled fashion, and just needed to notify the user, which was more of a status 200 response since it was a message to the user.
Anyways I found that this didn't work:
$event->setResponse(new Response(json_encode($returnArray), 200));
But if I added a header it works, Symfony looks for this header later and respects it. Without the header Symfony just assigns a 500 if you use an /Exception instead of an /HttpException
$event->setResponse(new Response(json_encode($returnArray), 200, array('X-Status-Code' => 200)));
I'm still new to this exception thing, so let me know if something I'm doing is wrong, but that header fixed my problems.

Catching Exceptions from library using Laravel 5.2

Pretty new to laravel, so I'm not exactly sure how it handles errors and how best to catch them.
I'm using a 3rd party game server connection library that can query game servers in order to pull data such as players, current map etc..
This library is called Steam Condenser : https://github.com/koraktor/steam-condenser
I have imported this using composer in my project and all seems to be working fine, however I'm having trouble with catching exceptions that are thrown by the library.
One example is where the game server you are querying is offline.
Here is my code:
public function show($server_name)
{
try{
SteamSocket::setTimeout(3000);
$server = server::associatedServer($server_name);
$server_info = new SourceServer($server->server_ip);
$server_info->rconAuth($server->server_rcon);
$players = $server_info->getPlayers();
$total_players = count($players);
$more_info = $server_info->getServerInfo();
$maps = $server_info->rconExec('maps *');
preg_match_all("/(?<=fs\)).*?(?=\.bsp)/", $maps, $map_list);
}catch(SocketException $e){
dd("error");
}
return view('server', compact('server', 'server_info', 'total_players', 'players', 'more_info', 'map_list'));
}
If the server is offline, it will throw a SocketException, which I try to catch, however this never seems to happen. I then get the error page with the trace.
This causes a bit of a problem as I wish to simply tell the end user that the server is offline, however I cannot do this if I can't catch this error.
Is there something wrong with my try/catch? Does laravel handle catching errors in this way? Is this an issue with the 3rd party library?
A couple things:
Does the trace lead to the SocketException or to a different error? It's possible that a different error is being caught before the SocketException can be thrown.
Your catch statement is catching SocketException. Are you importing the full namespace at the top of your PHP file? use SteamCondenser\Exceptions\SocketException;
Also for debugging purposes, you could do an exception "catch all" and dump the type of exception:
try {
...
}catch(\Exception $e){
dd(get_class($e));
}
If you still get the stack trace after trying the above code, then an error is being thrown before the try/catch block starts.

500 server error when saving Symfony entity

I need to couple my application with its database. To do this, I've generated an entity with doctrine:generate:entity. It's produced an entity with appropriate annotations for mapping. I've also used doctrine:schema:update --force to actually create the schema on the database server, which I can confirm it has done with phpMyAdmin.
In my controller I'm trying to simply insert a row like so:
public function testAction() {
$file = new File();
$file->setTest('A Foo Bar');
$em = $this->getDoctrine()->getManager();
$em->persist($file);
$em->flush();
return new JsonResponse(array('foo' => 'bar'));
}
The entity only has one field called test which is string and of length 255. When I request this URL through an AJAX request in my application, it throws back a very uninformative 500 Internal Server Error:
Oops! An Error Occurred
The server returned a "500 Internal Server Error".
Something is broken. Please e-mail us at [email] and let us know what you were doing when this error occurred. We will fix it as soon
as possible. Sorry for any inconvenience caused.
The PHP error logs also don't have any error information. This controller action does work if I remove the database manipulation stuff. The application is also running in the dev environment.
Is there any way I can get a more descriptive error message to at least tell me what's wrong?
This is a default error page that you get in production. You can customize it - http://symfony.com/doc/current/cookbook/controller/error_pages.html
You can catch and read an error creating ExceptionListener - http://symfony.com/doc/current/cookbook/event_dispatcher/event_listener.html
Also you can switch to dev environment to show error text and log.
If you just want dev logs but prod environment, you can copy contents of monolog section app/config/config_dev.yml to app/config/config_prod.yml.
If anyone here comes across this issue and is lost, the cause in my case was that I had specified a new #ORM\ManyToOne relationship and was persisting instead of merging the entity.
This in the past has returned a valid error, but in this case the php script was not handling it at all.

Categories