tylercd100/lern

Error on app()->make("lern")->record($exception)

muzafarali opened this issue · 15 comments

Hi,
i'm using
app()->make("lern")->record($exception); in render@Handler.php
and getting error below many time ..

Next Tylercd100\LERN\Exceptions\RecorderFailedException: SQLSTATE[HY000] [1045] Access denied for user 'forge'@'localhost' (using password: NO) (SQL: insert into exceptions_log (class, file, line, code, message, trace, status_code, method, data, url, updated_at, created_at) values (Illuminate\Database\QueryException, H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Database\Connection.php, 647, 1045, SQLSTATE[HY000] [1045] Access denied for user 'forge'@'localhost' (using password: NO) (SQL: select * from information_schema.tables where table_schema = forge and table_name = migrations), #0 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Database\Connection.php(607): Illuminate\Database\Connection->runQueryCallback('select * from i...', Array, Object(Closure))
#1 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Database\Connection.php(326): Illuminate\Database\Connection->run('select * from i...', Array, Object(Closure))
#2 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Database\Schema\MySqlBuilder.php(18): Illuminate\Database\Connection->select('select * from i...', Array)
#3 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php(221): Illuminate\Database\Schema\MySqlBuilder->hasTable('migrations')
#4 H:\xampp\htdocs\zapro\passoinstructor\vendor\kordy\ticketit\src\TicketitServiceProvider.php(30): Illuminate\Support\Facades\Facade::__callStatic('hasTable', Array)
#5 [internal function]: Kordy\Ticketit\TicketitServiceProvider->boot()
#6 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(29): call_user_func_array(Array, Array)
#7 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(87): Illuminate\Container\BoundMethod::Illuminate\Container{closure}()
#8 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(31): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure))
#9 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Container\Container.php(539): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL)
#10 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Foundation\Application.php(788): Illuminate\Container\Container->call(Array)
#11 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Foundation\Application.php(771): Illuminate\Foundation\Application->bootProvider(Object(Kordy\Ticketit\TicketitServiceProvider))
#12 [internal function]: Illuminate\Foundation\Application->Illuminate\Foundation{closure}(Object(Kordy\Ticketit\TicketitServiceProvider), 38)
#13 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Foundation\Application.php(772): array_walk(Array, Object(Closure))
#14 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Foundation\Bootstrap\BootProviders.php(17): Illuminate\Foundation\Application->boot()
#15 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Foundation\Application.php(208): Illuminate\Foundation\Bootstrap\BootProviders->bootstrap(Object(Illuminate\Foundation\Application))
#16 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(162): Illuminate\Foundation\Application->bootstrapWith(Array)
#17 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(146): Illuminate\Foundation\Http\Kernel->bootstrap()
#18 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(116): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
#19 H:\xampp\htdocs\zapro\passoinstructor\public\index.php(52): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#20 {main}, 0, GET, {"page":"3","name":""}, http://passoinstructor.dev/instructor/learner/skills/4, 2018-02-01 10:24:26, 2018-02-01 10:24:26)) in H:\xampp\htdocs\zapro\passoinstructor\vendor\tylercd100\lern\src\Components\Recorder.php:63
Stack trace:
#0 H:\xampp\htdocs\zapro\passoinstructor\vendor\tylercd100\lern\src\LERN.php(67): Tylercd100\LERN\Components\Recorder->record(Object(Illuminate\Database\QueryException))
#1 H:\xampp\htdocs\zapro\passoinstructor\app\Exceptions\Handler.php(68): Tylercd100\LERN\LERN->record(Object(Illuminate\Database\QueryException))
#2 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(326): App\Exceptions\Handler->render(Object(Illuminate\Http\Request), Object(Illuminate\Database\QueryException))
#3 H:\xampp\htdocs\zapro\passoinstructor\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(120): Illuminate\Foundation\Http\Kernel->renderException(Object(Illuminate\Http\Request), Object(Illuminate\Database\QueryException))
#4 H:\xampp\htdocs\zapro\passoinstructor\public\index.php(52): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#5 {main}

Are you sure that your App can connect to your database?
SQLSTATE[HY000] [1045] Access denied for user 'forge'@'localhost' (using password: NO)

Yes im sure my App is connected with database. And working on different things just for log i install your package and getting these errors many time in my log file..

i'm using laravel 5.4.x

I just want to add that if the application cannot connect to the database and we have opted to record the errors in the database, we will enter an infinite loop that will cause the app to flood to the notification system (in my case, I got a thousands of emails until the app timed out).

A quick fix I used was to change the default reporting function to:

if ($this->shouldReport($exception)) {
    if (app()->bound('lern')) {
        if ($exception instanceof \Doctrine\DBAL\Driver\PDOException && 1045 == $exception->getCode()) {
            app()->make('lern')->notify($exception);
        } else {
            app()->make('lern')->handle($exception);
        }
    }
}

Thank you EvilLooney!

I like this solution and I want to implement this and roll this out as a bug fix.

I am doing some reading on PDO error codes and it looks like the error codes are of type String according to the comments of this page (which explains the use of double equals in your code sample)

I also read that not every PDO driver utilizes the PDOException properly and may just pass "0" as the error code. People have suggested to use PDO::errorCode

So with that said, let me do some more testing today and get this bugger fixed.

-Tyler

I also want to point out that my solution is only if we cannot connect to the database. I assume that this could also happen if the table does not exist or some other database error (I haven't tested).

Is there any way we could leverage your RecorderFailedException exception for this?

Yes but it looks like with the current code it wont send a notification either. This could be changed.

Alright, 4 hours later and I have an update.

  1. I made it so RecorderFailedException will get sent on the notification channels.
  2. I added a test that checks for infinite loops by having it try to connect to a database that is not running.
  3. I added a Rate limit that defaults to 1/notification/second. It uses the Cache driver that you have set for your environment. You can change this by setting the config value "lern.ratelimit"

I am going to run this on one of my project's staging servers to verify the infinite loop is gone.

I'll be back with an update

Oops... forgot that merging pr's closes issues.

So version 4.5.0 is working as intended.

However in my case, if you use "database" as your queue driver paired with supervisor to restart your queue process whenever it fails. Supervisor tries to restart the process over and over which causes many notifications and memory overflow. This might be a bug related to laravel or supervisor, so I will look into it.

I'm not sure if your configuration is the same as mine @EvilLooney so let me know

4.5.1 has fixed my previous issue.

Good thinking for the supervisor / database queue driver combo.

However, we still have a problem if the Cache driver used is the database driver. My app completely crashes, even without some logging made into the laravel.log file.

K I'll look into this too.

Another problem we can have is that if, for some reason, the database has too many connections, we'll have a situation where we are flooding the database with INSERT queries (and sending out emails) which in turn exacerbates the too many connection problem.

Illuminate\Database\QueryException SQLSTATE[08004] [1040] Too many connections

Is there anyway to forgo all insertions of exceptions for these types of database problems?

Hey EvilLooney,

Is the too many connections exception being thrown on this line?
https://github.com/tylercd100/lern/blob/master/src/Components/Recorder.php#L77

Can you post a stack trace?

I'm sorry! My bad.

Your code is working fine as it's not adding these errors in the exceptions table; I did get 200 or so emails though. I should have double checked.