In app\Console\Kernel.php, I have two commands.
protected function schedule(Schedule $schedule)
{
$schedule->command("cron:batch-1")
->name("batch-1")
->everyMinute()
->runInBackground()
->withoutOverlapping()
->onFailure(function () {
Log::channel('cronlog')->error("cron:batch-1 is fail at" . Carbon::now());
});
$schedule->command("cron:batch-2")
->name("batch-2")
->everyMinute()
->runInBackground()
->withoutOverlapping()
->onFailure(function () {
Log::channel('cronlog')->error("cron:batch-2 is fail at" . Carbon::now());
});
}
Inside batch-1 command, following code is exists.
public function handle()
{
// Get tenant id
$tenants = Tenant::all;
foreach($tenants as $tenant) {
// clear cache to separate log
Artisan::call("config:cache");
$currentTenant = Tenant::find($tenant);
$this->closeApplication($currentTenant);
}
}
public function closeApplication($tenant)
{
// load multitenancy
$tenant->configure()->use();
// change log file path based on tenant
(new Tenancy())->configureLogFile();
// other logic code ...
Log::channel("cronlog")->info("[{$tenant->customer_name}] batch-1 command is running.");
}
Here is batch-2 command code.
public function handle()
{
// Get tenant id
$tenants = Tenant::all;
foreach($tenants as $tenant) {
// clear cache to separate log
Artisan::call("config:cache");
$currentTenant = Tenant::find($tenant);
$this->openApplication($currentTenant);
}
}
public function openApplication($tenant)
{
// load multitenancy
$tenant->configure()->use();
// change log file path based on tenant
(new Tenancy())->configureLogFile();
Log::channel("cronlog")->info("[{$tenant->customer_name}] batch-2 command is running.");
}
Both of the code is nearly the same. You will see (new Tenancy())->configureLogFile();
inside both code is to separate log file per tenant. Here is what I want to separate log file like following.
for tenant-1 => storage/logs/tenant-1/tenant-1_cronlog_{date}.log
for tenant-2 => storage/logs/tenant-2/tenant-2_cronlog_{date}.log
Here is the configureLogFile()
method.
public function configureLogFile()
{
// get current tenant key name
$currentTenant = (new Tenant())->currentTenantKeyName();
$customerKeyName = $currentTenant ?? null;
$directory = $customerKeyName . '/';
// get channel key as array data
$channels = array_keys(config('logging.channels'));
// loop all channel
foreach($channels as $channel) {
// if new channel is created by developer, we will use channel name as log file name
// eg: for `customlog` channel, file name will be `keyname_customlog.log`
$filePath = storage_path('logs/' . $directory . $customerKeyName . '_'.$channel.'.log');
config(['logging.channels.'.$channel.'.path' => $filePath]);
}
}
This code is changing log file path based on tenant with config()
helper.
First problem is, if I remove Artisan::call("config:cache");
from both command(batch-1, batch-2), log file is not separate per tenant. Subsequent tenant-2, tenant-3 logs are written into tenant-1 log file. Which is why I add Artisan::call("config:cache");
in both command.
Second problem is, when I add Artisan::call("config:cache");
in both command and these two commands are running at every minute(same time), I got following error.
Argument 2 passed to Facade\Ignition\QueryRecorder\QueryRecorder::__construct() must be of the type bool, null given, called in C:\laragon\www\api-career\vendor\facade\ignition\src\IgnitionServiceProvider.php on line 386 {"exception":"[object] (TypeError(code: 0): Argument 2 passed to Facade\\Ignition\\QueryRecorder\\QueryRecorder::__construct() must be of the type bool, null given, called in ...
When this error occur, commands are misbehaving. batch-1 or batch-2 cron is not running anymore. After I search why this error occur, I found it because of calling "config:cache". But, I'm not yet know how to solve. All I want is to separate log file per tenant. I have tried a lot of way like followig link, but it is not working.