Laravel 8 - 监听特定请求期间发生的 eloquent 事件
Laravel 8 - Listen to eloquent events made during a specific request
目前,我正在尝试将遥测库 (OpenTelemetry php lib) 连接到 Laravel 事件模型。这个想法是将跟踪转发给第三方服务。单个跟踪与请求和在请求期间进行的所有数据库调用一致。我创建了三个中间件组件:
- BeforeRequest:开始跟踪
- OnRequest:调用侦听数据库查询的事件侦听器(请参阅下面的代码段)并结束跟踪,以便将其发送到第三方服务
我的 OnRequest 中间件组件如下所示:
<?php
namespace App\Http\Middleware;
use App\Helpers\Otel\TraceProviderFactory;
use Closure;
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class OnRequest
{
public function handle(Request $request, Closure $next)
{
$provider = TraceProviderFactory::getTraceProvider($request->get('context_uuid'));
DB::listen(function (QueryExecuted $query) use ($provider){
$provider->startDbSpan($query);
});
$provider->endSpans();
return $next($request);
}
}
在这种情况下,数据库侦听调用被跳过,因为它是异步的。如何确保每个数据库查询都已注册?执行顺序很重要。一切都需要以正确的顺序进行,否则跟踪记录不会被正确记录。
我会在可终止的中间件中完成此操作(在将响应发送到客户端之后),以允许您记录从开始收听到发送响应之间的所有查询。这也不会阻止将响应返回给客户端。
...
class OnRequest
{
protected $provider;
public function handle(Request $request, Closure $next)
{
$this->provider = TraceProviderFactory::getTraceProvider($request->input('context_uuid'));
DB::listen(function (QueryExecuted $query) {
$this->provider->startDbSpan($query);
});
return $next($request);
}
public function terminate($request, $response)
{
$this->provider->endSpans();
}
}
您应该将此中间件设为单例,这样它就不会为可终止部分使用新实例。 (我们希望分配相同的 $provider
实例)。在服务提供商中注册单例:
public function register()
{
$this->app->singleton(OnRequest::class);
}
你只需要一个中间件就可以完成所有事情。
目前,我正在尝试将遥测库 (OpenTelemetry php lib) 连接到 Laravel 事件模型。这个想法是将跟踪转发给第三方服务。单个跟踪与请求和在请求期间进行的所有数据库调用一致。我创建了三个中间件组件:
- BeforeRequest:开始跟踪
- OnRequest:调用侦听数据库查询的事件侦听器(请参阅下面的代码段)并结束跟踪,以便将其发送到第三方服务
我的 OnRequest 中间件组件如下所示:
<?php
namespace App\Http\Middleware;
use App\Helpers\Otel\TraceProviderFactory;
use Closure;
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class OnRequest
{
public function handle(Request $request, Closure $next)
{
$provider = TraceProviderFactory::getTraceProvider($request->get('context_uuid'));
DB::listen(function (QueryExecuted $query) use ($provider){
$provider->startDbSpan($query);
});
$provider->endSpans();
return $next($request);
}
}
在这种情况下,数据库侦听调用被跳过,因为它是异步的。如何确保每个数据库查询都已注册?执行顺序很重要。一切都需要以正确的顺序进行,否则跟踪记录不会被正确记录。
我会在可终止的中间件中完成此操作(在将响应发送到客户端之后),以允许您记录从开始收听到发送响应之间的所有查询。这也不会阻止将响应返回给客户端。
...
class OnRequest
{
protected $provider;
public function handle(Request $request, Closure $next)
{
$this->provider = TraceProviderFactory::getTraceProvider($request->input('context_uuid'));
DB::listen(function (QueryExecuted $query) {
$this->provider->startDbSpan($query);
});
return $next($request);
}
public function terminate($request, $response)
{
$this->provider->endSpans();
}
}
您应该将此中间件设为单例,这样它就不会为可终止部分使用新实例。 (我们希望分配相同的 $provider
实例)。在服务提供商中注册单例:
public function register()
{
$this->app->singleton(OnRequest::class);
}
你只需要一个中间件就可以完成所有事情。