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()).
Related
I am using Laravel Log Facade in my app. And I have several services like Mandrill, Twilio, Stripe, etc., that need to be logged in separate file. But when I use Log::useFiles() to set separate file for one of the service wrapper class, like this:
Class Mailer
{
static function init()
{
Log::useFiles(storage_path('logs/mandrill-'.date("Y-m-d").'.log'));
}
static function send()
{
// some code here...
Log::error("Email not sent");
}
}
And I am ending up with log being written in both Laravel log file, and this Mandrill log file.
Is there a way to tell Log to write logs only in one file?
It's generally strange that it does that, because when I use directly Monolog, it writes only in one file, as it should. As far as I know Log Facade is using Monolog.
First of all, keep in mind that if you change the log handlers in your Mailer class you'll change them for the whole application.
Secondly, the reason that after your changes you get logs written to 2 files is that useFiles() does not overwrite the default log handler but adds a new handler to the handlers that Monolog will use. Therefore, you just add a second handler to the list and both of them handle the log message by saving them into different files.
Thirdly, Laravel's Log facade does not provide a way to replace the default handler - if you want to use it you need to use Monolog directly. You can access it by calling Log::getMonolog().
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.
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.
I am trying to create library that will write "error" messages in database, I do not think that I will be able to write PHPs errors nor CodeIgniters, but I can write my own "errors" something like
$this->error->write("User is not allowed to go in here");
I know there is a error handling already built in CodeIgniter on top of all it only supports writing errors/infos/debugs in file not database.
The real question is: how to get controller that called function.
Lets say I am in controller -> ./admin/settings.php and error ocures, code will call my library and I want it to store controller that called it. (I may be forced to send it as parameter but I don't want to write manually that it was fcn("error text", "/settings.php");
Assumed output: /controllers/admin/settings.php somewhere inside class that is called by controller.
You can use the router class to get this info
Also works with Codeigniter v3.0.x
To get the controller(class)
$this->router->class
To get the method(function)
$this->router->method
I have a project based on codeigniter. And I should use one class that extended from a codeigniter controller in another php file. But I didn't find the solution about how to teach another php file to see whole CI-project. Beyond that needed class can not inherit when i call it from other place.
I'm not 100% sure if this helps get you in the right direction, but kudos if it does!
Codeigniter routes the application depending on the environment state of the URI. What you need to do is set the environment and include the index view file like so:
$_SERVER["REQUEST_URI"] = "cms/2";
//Set GET action,method params etc
require_once "path/to/index.php";
When you load CI Index file it reads the SERVER Variable and others which you may have to find and execute the controller and method, I would also advise that you modify the library/view file as it may exit upon output causing your script to exit.
Also you may wis hto look into ob_start() to catch the buffer.