Hi,
This is a feature request for the logging infrastructure in Yii 2. Perhaps it’s already implemented, but I haven’t seen any examples of it yet.
Currently, in Yii 1, the Yii::log() method only accepts (or rather, only works without errors when you give it) a string as the first argument (the $message parameter). This is fine as long as you only want to log simple string messages, but there are other use cases as well.
Example use case
One such other use case is this: You want to create a custom log route that stores the log messages as structured data in a database, using AR. You want to do for example:
Yii::log(array(
'user'=>Yii::app()->user->name,
'previous_state'=>$this->state,
'message'=>"Power on requested for device {$this->name}.",
), CLogger::LEVEL_INFO, 'audit.power');
This would, using an ActiveLogRoute that saves data using an ActiveRecord model, effectively store the information in that model’s table like: log(id, tstamp, level, category, user, previous_state, message).
In the example above, the log table in question is specifically structured to match the type of logging at hand. There are of course other ways to do the models and tables as well; The common part is that one want to be able to log arrays of data and not just strings.
Usability features of the above use case
The key usability points here are that:
-
you use the existing log infrastructure, keeps code unified
-
you use AR models for the various log types you want, makes the code nice and clean
-
you can for example add validation and filtering to the logging
-
you can reuse these AR models for other purposes, for example presenting a nice search interface for your logs (CGridView for example)
Tried and proven useful
I already had this and a similar use case, so I have created ActiveLog, ActiveLogRoute and ActiveLogEntry classes to do all this, but it was unfortunate that the Yii::log() did not handle arrays, so I had to do some extra work to fix that.
In summary what I needed to do was supply a custom log() method that wraps array "messages" in a ActiveLogEntry, which provides a __toString() and also its own stack trace generation.
This object (or the untouched string message) is then passed to the regular Yii::log(). The wrapped log message/array survives Yii logging infrastructure because it is now an ActiveLogEntry that can be "read" as a string due to __toString().
Finally the ActiveLogRoute simply saves the stuff using AR in its processLogs() method, supporting scenarios, validation, events and all the nice things we have in AR.
If Yii::log() had not been restricted to strings only, I could have done without one or two of these four classes (the fourth being the AR model). I also made a wrapper Yii class so that one can use Yii::log() instead of ActiveLog::log(), and this wouldn’t have been necessary either
Puppy eyes
Ok, this was my attempt at describing a super nice thing to have with a real world use case. I’ve been very happy to be able to log structured data using the basic log infrastructure in Yii and its AR. I’m doing it both to structured/regular tables in a relational database as well as to JSON format.
Is this something we can get for Yii 2.0? I’ll be happy to elaborate on the details as needed!