Laravel 5 > Using monolog introspection processor - php

I have configured Laravel 5 to use a custom logging configuration (default is way too simple). I've added monolog's IntrospectionProcessor to log the file name and line number of the log call.
The problem is that all lines get the same file and line number:
[2015-06-29 17:31:46] local.DEBUG (/home/vagrant/project/vendor/laravel/framework/src/Illuminate/Log/Writer.php#201): Loading view... [192.168.10.1 - GET /loans/create]
Is there a way to config the IntrospectionProcessor to print the actual lines and not the facade ones?
If I do Log::getMonolog()->info('Hello'); it works and prints the correct file and line number... but I don't know how safe is to avoid calling the Writer.writeLog function because it fires a log event (is it safe to not fire that event?).

(Only tried in Laravel 4.2!)
When pushing the Introspection Processor to Monolog it is possible to give an skipClassesPartial array as second parameter in the IntrospectionProcessor contructor. With this array it is possible to skip the Laravel Illuminate classes and the logger logs the class calling the log method.
$log->pushProcessor(new IntrospectionProcessor(Logger::DEBUG, array('Illuminate\\')));
also see: https://github.com/Seldaek/monolog/blob/master/src/Monolog/Processor/IntrospectionProcessor.php

I know this is an old question but I thought I'd give a quick update because it's pretty easy to get this done now.
I haven't tried with Laravel but My own logging mechanism is within a LoggingService wrapper class. As such the introspection was only giving details about the service rather than the caller.
after reading Matt Topolski's answer, I had a look in the IntrospectionProcessor.php. the constructor looks like this:
__construct($level = Logger::DEBUG, array $skipClassesPartials = array(), $skipStackFramesCount = 0)
All I had to do was add the processor like this:
log->pushProcessor(new IntrospectionProcessor(Logger::DEBUG, array(), 1));

This is actually the expected functionality unless you're having the handler process the logs directly (check out the comments at the top of IntrospectionProcessor.php). My guess is you have a wrapper function around the logger and you're calling it from Writer.php -- BUT
If you look at the code for IntrospectionProcessor.php you'll see a bit of code on lines 81 to 87 that decides how to format that stack trace, and it still has access to the stack. If you bump the $i values for $trace[$i - 1] / $trace[$i] up one (aka $trace[$i]/$trace[$i + 1] respectively) you can 'climb' the stack back to where you want.
It's important to note that the 'class' and 'function' parts of the trace need to be one level of the stack higher than the 'file' and 'line.'
On a personal (plz dont mod me bruhs) note, I'd like to see functionality to include a stack offset when throwing the log in. I know what function I want to blame if an error shoots out when I write the error_log('ut oh') but I might(will) forget that by the time the 'ut oh' comes.

Related

Add custom data to laravel log

I want for a certain Laravel Job class to change the behaviour of the logging system. This is how my logs look right now:
[2018-08-22 08:31:24] production.INFO: [do-harvester-job]
[template: 598 - theme: 2592]Doing tasks
This is achieved by the following code:
\Log::info("{$this->harvester_job->log_prefix()}Doing tasks");
The problem is that I have a lot of log calls like this one and it gets cumbersome to always add the call to the log_prefix method.
Is there any way of prepending that info to the log without having to concatenate it inside the log call?
If you are facing problems in displaying the class data inside log file then you can use json_encode($className->fetchAllData()).

Call artisan command from the same command

In the handle of your custom Laravel command, can you call the command again? Like this, described using sort of pseudo-code:
public function handle() {
code..
code..
$this->importantValue = $this->option('value'); //value is 'hello'
if(something) {
//call of the same command is made, but with different arguments or options
//command does stuff and ends successfully
$this->call('myself' [
'value' => 'ahoy'
];
//I expect the handle to be returned to the original command
}
var_dump($this->importantValue); //this equals 'ahoy'
}
Why is this? What does that newly called command has in common with the original within which it had been called?
EDIT: The newly called command would not reach the condition something it would not call itself again (forever). The original command seems to pick up from where it left (before calling itself the first and only time) yet it seems it has had inherited the "children's" variables.
I do think that calling Artisan::call() instead of $this->call() might avoid that problem (note that avoiding is not the same as solving)...
#t-maxx: I'm getting the exact same issue and I'm not sure that #ben understands.
I have a command that is recursive, based on an argument, depth. The depth argument is set to a protected property as one of the first steps in handle(). Then, if depth is greater than zero, it calls itself (via $this->call()), but passing $this->depth - 1. I watch each successive call and it just goes down and down and down, never plateauing or bouncing up was the recursion would allow and as one would expect.
So...while I'm not 100% sure what's going on, I'm thinking of getting the depth option once, but passing it around as a variable (versus a property on the object). This is ugly, I think, but it may be the only solution until this is recognized and resolved. On the other hand, it could be that we're both doing the wrong thing.
Calling Artisan::call() for me leads to other issues that I'd rather avoid. The command I'm working with writes to a file and I don't want a bunch of separate commands competing for the same file.
Yes, you can Programmatically Executing Commands using Artisan::call
Artisan::call('myself', [
'value' => 'ahoy'
]);

phpunit check logs file

I have several integration tests with phpunit,
and in the proccess of the tests there are some logs written to files in the system.
I would like to check if a line was written during a test, is that possible?
example:
/** #test */
function action_that_writes_to_log() {
$this->call('GET', 'path/to/action', [], [], $requestXml);
//I want this:
$this->assertFileHas('the log line written', '/log/file/path.log');
}
The obvious way:
Implementing a custom assertion method, like the one you propose: assertFileHas. It's quite easy, just check if the string appears in the file. The problem you can get is that the line can already exist from another test or the same test already run. A possible solution for this is deleting the logs content before each test or test class, depending on your needs. You would need a method that deletes the logs and call it from setUp or setUpBeforeClass.
I would go with another approach: mocking the logging component, and checking that the right call is being done:
$logger_mock->expects($this->once())
->method('log')
->with($this->equalTo('the log line written'));
This makes easy to test that the components are logging the right messages, but you also need to implement a test that verifies that the logger is capable of actually writting to the file. But it's easier to implement that test once, and then just check that each component calls the logging method.

log4php will not work properly

So I recently discovered that the log4* package was available for PHP and upon seeing this eagerly downloaded the latest from the log4php website and followed the installation instructions. The instructions indicate that one is to download the tar package, untar, and place the following directory in a place of one's choosing: log4php/src/main/php
Therefore I copied the contents of log4php/src/main/php into my lib dir under lib/log4php.
In my script, as required, I required the 'Logger.php' class and indicated a properties file to manage my appenders. The properties file, log4php.properties, is located on my filesystem at "/home1/ioforgec/www/devlab/pnotes/config/log4php.properties".
Here is the logfile content:
#
# Example Logger
#
log4php.appender.EA1 = LoggerAppenderConsole
log4php.appender.EA1.target = STDOUT
log4php.appender.EA1.layout = LoggerLayoutPattern
log4php.appender.EA1.ConversionPattern = "%m"
log4php.appender.EA1.threshold = FATAL
log4php.exampleLogger = FATAL, EA1
So here is a copy of my script that implements (more or less 'wraps' the log4php functionality):
<?php
require_once('/home1/ioforgec/www/devlab/pnotes/lib/log4php/Logger.php');
class LogUtil
{
public $logger;
public $properties_file = "/home1/ioforgec/www/devlab/pnotes/config/log4php.properties";
public static function logExample($msg)
{
Logger::configure($properties_file);
$logger = Logger::getLogger("example");
$logger->debug("Shouldnt see this print because of config max level FATAL");
$logger->fatal($msg);
}
}
?>
In order to test that this is working properly, the following script calls the LogUtil.php shown above:
#!/usr/bin/php
<?php
require_once("lib/utils/LogUtil.php");
LogUtil::logExample("example message");
?>
So, despite configuring the example logger to format the messages as the plain message, despite setting the level of the logger to a max of FATAL, not only in the logger declaration but also in the threshold command, the print to the console looks to me like the default root logger:
Mon Oct 18 20:30:05 2010,705 [827] DEBUG example - Shouldnt see this print because of config max level FATAL
Mon Oct 18 20:30:05 2010,711 [827] FATAL example - example message
I see the print statement without the plain formatting as specified, and I see two print statements, the debug print (which should never have printed due to the setting of FATAL on the logger config - FATAL is MUCH higher than DEBUG)
What on earth am I doing wrong? Ive tried every combination of setup I can possibly think of. Does anyone have any suggestions?
Edit - Update - This is still an issue. No progress.
Edit2 - Really? Has no one on this forum tried to use this very popular logging package and its incarnation as a PHP module?
I have tried every conceivable avenue to try and get my question answered, including the log4php user's mailing list.
After many many more hours of manipulating the configuration file I have discovered a small, yet critically important factoid. In order to specify a 'logger' you must name it under the 'logger' hierarchy and its appenders under the 'appender' hierarchy, etc etc. For example:
# for the 'console' logger named 'example' we first define the appender:
log4php.appender.consoleAppender = LoggerAppenderConsole
log4php.appender.consoleAppender.target = STDOUT
log4php.appender.consoleAppender.layout = LoggerLayoutSimple
# we then assign the appender and the minimum log level to the logger:
log4php.logger.example = WARN, consoleAppender
My mistake was in seeing the root logger hierarchy name 'log4php.rootLogger' and assuming that in order to assign a logger one need only name a value for 'log4php.lognameLogger'. Sadly this is no excuse as there was an example, buried, in the documentation. I suppose finding it at 9+ hours is better than not at all :)
Thanks to those who reminded me that there was more debugging work to be done, I appreciated the reminder to keep trying

systematizing error codes for a web app in php?

I'm working on a class-based php web app. I have some places where objects are interacting, and I have certain situations where I'm using error codes to communicate to the end user -- typically when form values are missing or invalid. These are situations where exceptions are unwarranted ( and I'm not sure I could avoid the situations with exceptions anyways).
In one object, I have some 20 code numbers, each of which correspond to a user-facing message, and a admin/developer-facing message, so both parties know what's going on. Now that I've worked over the code several times, I find that it's difficult to quickly figure out what code numbers in the series I've already used, so I accidentally create conflicting code numbers. For instance, I just did that today with 12, 13, 14 and 15.
How can I better organize this so I don't create conflicting error codes? Should I create one singleton class, errorCodes, that has a master list of all error codes for all classes, systematizing them across the whole web app? Or should each object have its own set of error codes, when appropriate, and I just keep a list in the commentary of the object, to use and update that as I go along?
Edit: So I'm liking the suggestions to use constants or named constants within the class. That gives me a single place where I programatically define and keep track of error codes and their messages.
The next question: what kind of interface do I provide to the outside world for this class' error codes and messages? Do I do something like triggerError(20) in the class, and then provide a public method to return the error code, the string constant, and the user- and admin-facing message?
You could create a couple of defines to create named constants for all your error codes :
define('ERROR_CODE_SQL_QUERY', 1);
define('ERROR_CODE_PAGE_NOT_FOUND', 2);
define('ERROR_CODE_NOT_ALLOWED', 3);
// and so on
And, then, use the constants in your code :
if ($errorCode == ERROR_CODE_SQL_QUERY) {
// deal with SQL errors
}
With that, nowhere in your code you'll use the numerical value : everywhere (except in the on and only file where you put the defines), you'll use the codes.
It means :
Less risk of errors, as all numerical values are set in only one file
Less risk of errors, as you'll use the constants, that have a name which indicates what it means
And code that's easier to read.
Another idea could be to create a class to deal with errors :
class Error {
const CODE_SQL_QUERY = 1;
const CODE_PAGE_NOT_FOUND = 2;
const CODE_NOT_ALLOWED = 3;
// Add some methods here, if needed
}
And, then, use something like this :
if ($errorCode == Error::CODE_SQL_QUERY) {
// deal with SQL errors
}
Which one is the best ?
It's probably a matter of personnal preferences... If you need to add some methods to deal with the errors, using a class might be useful. Else, defines are a great solution too.
At the very least, can you bump the code numbers up to be class constants or members?
class MyErrorProneClass {
const TURNED_INTO_A_NEWT = 12;
...
public function dontBurnMe() {
// echo your error here using self::TURNED_INTO_A_NEWT
}
This way you can manage the errors in the same place where you use them, rather than having to maintenance a large central file. I tried something to that effect in the past and it becomes difficult to keep up.
Generating error numbers programmatically may be a better long-term solution. If you could use information about the file or line number (__FILE__ and __LINE__ respectively), that would help.
Hope that moves in the right direction at least.
Thanks, Joe
Edit:
A class member would follow this syntax instead:
class MyErrorProneClass {
protected static $turnedIntoANewt = 12;
...
public function dontBurnMe() {
// echo your error here using self::$turnedIntoANewt
}
Since constants are public by default, you can access them from other classes directly if you want. So, from the outside, the error would be referenced as:
MyErrorProneClass::TURNED_INTO_A_NEWT
For associating to messages, you would use a mapping (either in a database, or in some localization file) from error ID (and frontend/backend) to displayed string. This use of keys for messages isn't optimal, but it would allow you to change error messages without changing code as well.
If you don't know already it might be an idea to use trigger_error (), plus an error handler if you want to present the user with a better error message.
Have you thought about using exceptions? They may be a good choice for your problem here although adding them to your project now would probably require some restructuring.
You can extend the basic exception class so it fits your problem in terms the of user / developer error message separation.

Categories