You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel多域名场景下运行时设置默认日志通道的优化方案

更优实现方案

方案1:分层统一配置(适配不同入口类型)

针对HTTP请求、命令、队列Job三类入口做统一处理,避免重复编写切换代码:

1.1 HTTP请求:用中间件自动绑定

创建SetDomainLogChannel中间件,根据控制器命名空间判断所属域名模块,自动切换日志通道:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class SetDomainLogChannel
{
    public function handle(Request $request, Closure $next)
    {
        $controllerAction = $request->route()->getAction();
        $namespace = $controllerAction['namespace'] ?? '';
        
        // 假设域名模块命名空间为App\Domains\App1、App\Domains\App2
        if (str_contains($namespace, 'App\Domains\App1')) {
            config(['logging.default' => 'app-1']);
        } elseif (str_contains($namespace, 'App\Domains\App2')) {
            config(['logging.default' => 'app-2']);
        }

        return $next($request);
    }
}

将该中间件注册到对应域名模块的路由组中,无需每个控制器手动设置。

1.2 命令:自定义基类统一处理

给每个域名模块的命令创建专属基类,在基类的handle方法开头统一配置日志通道:

<?php

namespace App\Domains\App1\Console;

use Illuminate\Console\Command;

abstract class App1BaseCommand extends Command
{
    public function handle()
    {
        config(['logging.default' => 'app-1']);
        return $this->handleApp1Command();
    }

    // 子类需实现此方法编写业务逻辑
    abstract protected function handleApp1Command();
}

后续该域名下的所有命令都继承这个基类即可。

1.3 队列Job:基类统一配置

和命令逻辑一致,给每个域名模块的Job创建基类:

<?php

namespace App\Domains\App1\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

abstract class App1BaseJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function handle()
    {
        config(['logging.default' => 'app-1']);
        return $this->handleApp1Job();
    }

    abstract protected function handleApp1Job();
}

该域名下的所有Job继承此基类,无需重复配置。

方案2:全局动态日志通道解析

自定义日志逻辑,让Laravel自动根据当前执行的域名模块选择日志通道:

2.1 自定义DomainAwareLogger类

继承Laravel默认Logger,构造时动态判断所属域名并切换通道:

<?php

namespace App\Logging;

use Illuminate\Log\Logger;
use Monolog\Logger as MonologLogger;

class DomainAwareLogger extends Logger
{
    public function __construct(MonologLogger $monolog)
    {
        parent::__construct($monolog);
        $channel = $this->determineDomainChannel();
        $this->setDefaultDriver($channel);
    }

    protected function determineDomainChannel(): string
    {
        $caller = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2] ?? [];
        $class = $caller['class'] ?? '';
        
        if (str_contains($class, 'App\Domains\App1')) {
            return 'app-1';
        } elseif (str_contains($class, 'App\Domains\App2')) {
            return 'app-2';
        }
        
        return config('logging.default');
    }
}

2.2 替换默认日志服务绑定

在AppServiceProvider的register方法中替换默认Logger:

public function register()
{
    $this->app->bind('log', function ($app) {
        return new \App\Logging\DomainAwareLogger($app['monolog']);
    });
}

此后全局日志会自动根据执行代码所属域名模块选择对应通道,无需手动干预。

方案3:Monolog处理器实现多文件写入

若需同时保留全局日志和域名独立日志,可通过Monolog处理器动态分流:

// 在config/logging.php的stack通道中添加自定义处理器
'channels' => [
    'stack' => [
        'driver' => 'stack',
        'channels' => ['single'],
        'processors' => [\App\Logging\DomainLogProcessor::class],
    ],
    // 其他通道配置...
],

创建处理器类:

<?php

namespace App\Logging;

use Monolog\Handler\StreamHandler;
use Monolog\Processor\ProcessorInterface;

class DomainLogProcessor implements ProcessorInterface
{
    public function __invoke(array $record): array
    {
        $caller = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1] ?? [];
        $class = $caller['class'] ?? '';
        $domain = 'default';
        
        if (str_contains($class, 'App\Domains\App1')) {
            $domain = 'app-1';
        } elseif (str_contains($class, 'App\Domains\App2')) {
            $domain = 'app-2';
        }

        // 动态添加对应域名的日志文件处理器
        $handler = new StreamHandler(storage_path("logs/{$domain}.log"));
        $record['logger']->pushHandler($handler);

        return $record;
    }
}

此方案可实现单条日志同时写入全局文件和域名专属文件。


内容的提问来源于stack exchange,提问作者CXJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 14:25:30