BugDeveloper
BugDeveloper

Reputation: 235

Laravel model related logs

I develop a pretty big web application using laravel. Logging to a single file or daily files seems too messy for me.

My purpose is to create error logs which will be categorised and easy for retrieval to show on front-end for tech support. E.g. user entered wrong api-key, email, whatever.

P.S. Users don't always understand meaning of the error showed so they contact tech support.

Example for better understanding:

Suppose I have model relations: User->hasMany->Project and in some project appears an exception I want it to be written and related to the project. e.t.c. So I could do something like $some_project_model->logs()->get() and tech support got all logs related to certain project.

What I have in my mind is separate table for logs which is related to certain Eloquent models. But to do so ExceptionHandler needs to know to which model an Exception is related to.

So how this can be implemented? Maybe I could assign custom ExceptionHandler to certain class?

Thank you for any suggestions.

Upvotes: 2

Views: 959

Answers (2)

BugDeveloper
BugDeveloper

Reputation: 235

So I've actually found a proper solution:

First of all it's needed to create Log table with polymorphic relation. Then to catch all the exceptions in certain context __call magic method can be used. __call method allows to wrap every object method call with custom code. Try-catch in this case.

Example:

class Loggable
{

    public function __call($method, $arguments)
    {
        try {
            return call_user_func_array([$this->certain_obj, $method], $arguments);
        } catch (Exception $e) {
            //creating new $log orm
            $this->get_orm()->loggable()->save($log);
        }
    }

    protected function do_something() {
        //something is going on
        throw new \Exception();
    }
}

$loggable_obj = new Loggable();
$loggable_obj->do_something();

To make it work, you must make all loggable methods private or protected.

In case if you think that 'encapsulation' is not just another difficult word you can achieve the same result using proxy class.

Example:

class Proxy
{
    private $some_obj;

    public function __construct($some_obj)
    {
        $this->some_obj = $some_obj;
    }

    public function __call($method, $arguments)
    {
        try {
            return call_user_func_array([$this->some_obj, $method], $arguments);
        } catch (Exception $e) {
            //creating new $log orm
            $this->some_obj->get_orm()->loggable()->save($log);
        }
    }
}

$proxy = new Proxy($some_obj);
$proxy->whatever_method($foo, $bar);

So, in both cases I can get all logs related to some exact orm by calling ->logs()->get() on it.

Not a rocket science at all.

Upvotes: 2

madz
madz

Reputation: 1002

One approach might be to create your own custom exception (sub)class which you could add model and/or project information to at the point of throwing the exception. Then this information would be available in the ExceptionHandler.

You wouldn't have it for built in or third-party exception types though. For those you'd end up having to catch and rethrow where possible (and necessary), wrapping in your custom exception class, which probably isn't ideal.

Upvotes: 0

Related Questions