How to create multiple log files in laravel? - laravel

Like the state itself, I want to create multiple Log files for different processes.
I am using Laravel-8.
I have also created the 1 logging file with the help of logging.php in the config folder.
I want to keep track of my created commands with their own separate log file.
How can I create my separate log file for that commands?
I did this by having only a log for daily. "config/logging.php"
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['daily'],
'ignore_exceptions' => false,
]...,
]

You should use config/logging.php to create custom channel for each command
e.g.
'CHANNEL_NAME' => [
'driver' => 'single',
'path' => storage_path('logs/LOG_FILE_NAME.log'),
'level' => 'DESIRED_LEVEL',
],
and change CHANNEL_NAME, LOG_FILE_NAME and DESIRED_LEVEL values as you want.
Note: 'level' => 'DESIRED_LEVEL' is optional. it can be single level or array of levels (laravel v8.x).
Then when you want to log anything in your command class, Log like following code
Usage:
Log::channel('CHANNEL_NAME')
->info('Something happened!');

Below code will generate custom log file.
try{
//Your code here
}catch(\Exception $e){
$cusLog = new Logger('stack');
$err_file_name = $task_id."_".time();
$syncHistory['file_name'] = $err_file_name;
$cusLog->pushHandler(new StreamHandler(storage_path('logs/'.$err_file_name.'.log')), Logger::INFO);
$cusLog->info('error', ['Exception'=>$e->getTraceAsString(),'message'=>$e->getMessage()]);
}
Hope this will be useful.

Related

Laravel:prepend new log to log file

I'm looking for a way to prepend (instead of append) new logs to the log file.
The problem is for the big logfile, I should scroll a lot to see new logs.
First what you do is add a entry in config/logging.php like this:
'newLog' => [
'driver' => 'single',
'path' => storage_path('logs/newLog.log'),
'level' => env('LOG_LEVEL', 'debug'),
],
Understand the Log level and driver system of laravel here.
I hope I could help you.

Laravel logging to to custom channel does not consider minimum level

So i made a custom logging handler with a custom logger to log to db, and it works correctly.
What i cannot manage to work is the minimum loggin level define in the configuration.
To test it i made a stack with single and my custom channel (let's call it database), hanving both a error level, and logged a message for every log level with artisan: the daily file contains 4 messages, but my custom channel has 8 messages while i expected only 4.
Testing with a stack of single and daily instead work correctly, so this makes me think that i have to handle the minimum loggin level in my custom classes, but i couldn't find anywhere something that tells it explicitly.
Is not a problem to update my custom classes to check the log level, but i want to be sure that i'm not mistaking something else about laravel logging.
config/logging.php
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['single', 'daily'],
//'channels' => ['single', 'database'],
'ignore_exceptions' => false,
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => 'error',
],
'database' => [
'driver' => 'custom',
'handler' => App\Logging\CustomLoggingHandler::class,
'via' => App\Logging\CustomLogger::class,
'level' => env('MIN_DB_LOGGING_LEVEL', 'error'),
],
],

How do I make Laravel write a log showing my problem?

I'm writing my first Laravel app that also includes Vue. I'm pretty new to both Laravel and Vue so please be gentle ;-) I'm using Laravel 8.4.x and Vue 2.6.12 on Windows 10.
In my very first axios invocation, I'm trying to write of a single record to a database table in a submit method of my Vue component, I'm getting Http status code 500, internal server error. The response in the console says that Laravel doesn't see a controller with the name ToDoController. I have no idea why that would be since I created it properly with php artisan and I can see it in VS Code.
In looking at other posts to try to understand this problem, I see that people recommend looking in the server logs to find out more information. I'm not sure if the logs will have information not found in the response situated in the browser console but I won't know until I look at it. The problem is that I don't know where to look for my log.
According to the Laravel docs, logging is governed by config/logging.php and that file says:
<?php
use Monolog\Handler\NullHandler;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\SyslogUdpHandler;
return [
/*
|--------------------------------------------------------------------------
| Default Log Channel
|--------------------------------------------------------------------------
|
| This option defines the default log channel that gets used when writing
| messages to the logs. The name specified in this option should match
| one of the channels defined in the "channels" configuration array.
|
*/
'default' => env('LOG_CHANNEL', 'stack'),
/*
|--------------------------------------------------------------------------
| Log Channels
|--------------------------------------------------------------------------
|
| Here you may configure the log channels for your application. Out of
| the box, Laravel uses the Monolog PHP logging library. This gives
| you a variety of powerful log handlers / formatters to utilize.
|
| Available Drivers: "single", "daily", "slack", "syslog",
| "errorlog", "monolog",
| "custom", "stack"
|
*/
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['single'],
'ignore_exceptions' => false,
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
'days' => 14,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => 'Laravel Log',
'emoji' => ':boom:',
'level' => env('LOG_LEVEL', 'critical'),
],
'papertrail' => [
'driver' => 'monolog',
'level' => env('LOG_LEVEL', 'debug'),
'handler' => SyslogUdpHandler::class,
'handler_with' => [
'host' => env('PAPERTRAIL_URL'),
'port' => env('PAPERTRAIL_PORT'),
],
],
'stderr' => [
'driver' => 'monolog',
'handler' => StreamHandler::class,
'formatter' => env('LOG_STDERR_FORMATTER'),
'with' => [
'stream' => 'php://stderr',
],
],
'syslog' => [
'driver' => 'syslog',
'level' => env('LOG_LEVEL', 'debug'),
],
'errorlog' => [
'driver' => 'errorlog',
'level' => env('LOG_LEVEL', 'debug'),
],
'null' => [
'driver' => 'monolog',
'handler' => NullHandler::class,
],
'emergency' => [
'path' => storage_path('logs/laravel.log'),
],
],
];
If I'm understanding this correctly, that means that errors at DEBUG or above are being written to logs/laravel.log, which I should be seeing in VS Code. But I do not even have a logs directory, let alone a laravel.log file.
Do I need to do something to create these logs in the first place as part of creating a new project? If so, what? If not, why don't I see my log? A server error is significant enough to get written into the log, right?
Also, while we're on the subject of logs, I have a chicken and egg question: does the value of LOG_CHANNEL in the logging.php file get set from the .env file or does the .env file get the value in the logging.php file? In other words, if I want to change my logging behaviour, which one do I alter?
The logs directory is located in the storage directory. So it's storage/logs/laravel.log.
Also, you can choose to log anything you want to using the Log facade. See laravel writing log messages [https://laravel.com/docs/8.x/logging#writing-log-messages]. Anything that is wrapped in the env() function is being pulled from the env file. The second param allows you to set a default if that value is not set or available in the env file. 1
#Donkarnash - I strongly suspect you've identified the problem. I'm not up on the new features of Laravel 8. What would my Route look like if I have a FQCN for the controller? I've tried all the variations I can think of but nothing works, including url('app/Http/Controllers/ToDoController')
Since Laravel 8 the default namespace App\Http\Controllers is not set in the RouteServiceProvider - which is a welcome change.
So now when defining routes in routes files say routes/web.php FQCN of the controller must be used
use App\Http\Controllers\ToDoController;
Route::get('/todos', [ToDoController::class, 'index']);
//OR without importing the use statement
Route::get('/todos', [\App\Http\Controllers\ToDoController::class, 'index']);
If you want you can also use namespace method for route groups
Route::namespace('App\Http\Controllers')
->group(function(){
Route::get('/todos', 'ToDoController#index');
Route::get('/todos/{todo}', 'ToDoController#show');
});
Using FQCN as in either importing use statement or inline also provides benefits of easy navigation and code suggestions in IDE's
To revert back to the old convention and set default namespace you should declare
$namespace in RouteServiceProvider
/**
* The controller namespace for the application.
*
* When present, controller route declarations will automatically be prefixed with this namespace.
*
* #var string|null
*/
protected $namespace = 'App\\Http\\Controllers';

Laravel upload via FTP prevent overriding live logs

I am updating my laravel project via FTP.
I set override all files, where edit date changed.
Problem:
It overrides the live logs with the dev logs, because the name of the log file is the same.
I wanted to change log names (could save it in .env, because live project has its own .env), but I have not found a way to do it.
Any other ideas?
Just exclude logs file/dir when copying files instead of overriding it?
Here is my solution.
Go to logging.php and edit this condig:
'single' => [
'driver' => 'single',
//'path' => storage_path('logs/laravel.log'),
'path' => storage_path(env('LOG_PATH')),
'level' => 'debug',
],
'daily' => [
'driver' => 'daily',
//'path' => storage_path('logs/laravel.log'),
'path' => storage_path(env('LOG_PATH')),
'level' => 'debug',
'days' => 14,
]
Because the live project has a different .env, you can define a different folder or filename and it will work.

How do I disable a log channel on local and testing environment

In my application I have these log channels:
'general' => [
'driver' => 'single',
'path' => storage_path('logs/general.log'),
'level' => 'debug',
],
'jobs' => [
'driver' => 'stack',
'channels' => [
'general',
'slack'
],
],
'slack' => [
'driver' => 'slack',
'url' => /*Censored Hook URL*/,
'username' => 'MyApp',
'emoji' => ':gear:',
'level' => 'debug',
],
When I log in job channel I want not to log into slack log when on local or testing environment in order to avoid having duplicate and extremely unwanted logs on the shared log channel on the slack.
So how I can specify the environments that the slack channel will be able to write logs. A dirty approach is to specify manually which logs will write in to via this snippet of code:
if(!App::environment(['local','testing')){
Log::channel('jobs')->info('Blah blah blah');
} else {
Log::channel('general')->info('Blah blah blah');
}
But using the code above, I am afraid that will turn my codebase into a diffucult-to-read-one. So do you know an elegant solution in order to process my logs?
You could simply split jobs into 2 entrys, example jobs and jobs_without_slack, let jobs be as is and jobs_without_slack will be configured without slack in it's channels. Then use different .env.xy files for testing (.env.testing), local, develop (.env.develop) and so on and set the LOG_CHANNEL to the correct logging, so you do not need to change a line of code in your logic ;)

Resources