当前位置: 首页 > news >正文

Laravel分布式全链路追踪实战

我以larevel框架做分布式全链路追踪为实例

安装必要的包

composer require jaeger/jaeger-client-php
composer require opentracing/opentracing

创建 Service Provider

php artisan make:provider TracingServiceProvider
<?php
// app/Providers/TracingServiceProvider.phpnamespace App\Providers;use Jaeger\Config;
use OpenTracing\GlobalTracer;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Log;class TracingServiceProvider extends ServiceProvider
{public function register(){$this->app->singleton('jaeger.tracer', function () {$config = new Config(['sampler' => ['type' => 'const','param' => true,],'logging' => true,'local_agent' => ['reporting_host' => env('JAEGER_AGENT_HOST', 'localhost'),'reporting_port' => env('JAEGER_AGENT_PORT', 6831),],],env('APP_NAME', 'laravel-app'));return $config->initializeTracer();});// 设置全局 tracerGlobalTracer::set($this->app->make('jaeger.tracer'));}public function boot(){//}
}

注册 Service Provider

// config/app.php
'providers' => [// ...App\Providers\TracingServiceProvider::class,
],

创建中间件

php artisan make:middleware TracingMiddleware
<?php
// app/Http/Middleware/TracingMiddleware.phpnamespace App\Http\Middleware;use Closure;
use OpenTracing\GlobalTracer;
use OpenTracing\Tags;
use Illuminate\Http\Request;class TracingMiddleware
{public function handle(Request $request, Closure $next){$tracer = GlobalTracer::get();// 从请求头中提取追踪上下文$spanContext = $tracer->extract(\OpenTracing\Formats\HTTP_HEADERS,$request->headers->all());$scope = $tracer->startActiveSpan('http.request',['child_of' => $spanContext,'tags' => [Tags\HTTP_METHOD => $request->method(),Tags\HTTP_URL => $request->fullUrl(),'http.host' => $request->getHost(),'http.path' => $request->path(),'http.query' => $request->getQueryString() ?: '','http.user_agent' => $request->userAgent(),'http.client_ip' => $request->ip(),]]);// 将 span 存储到请求中,供后续使用$request->attributes->set('tracing_scope', $scope);try {$response = $next($request);$scope->getSpan()->setTag(Tags\HTTP_STATUS_CODE, $response->getStatusCode());return $response;} catch (\Exception $e) {$scope->getSpan()->setTag(Tags\ERROR, true);$scope->getSpan()->log(['event' => 'error','error.kind' => get_class($e),'message' => $e->getMessage(),'stack' => $e->getTraceAsString(),]);throw $e;}}public function terminate($request, $response){if ($request->attributes->has('tracing_scope')) {$scope = $request->attributes->get('tracing_scope');$scope->close();}}
}

注册中间件

// app/Http/Kernel.php
protected $middleware = [// ...\App\Http\Middleware\TracingMiddleware::class,
];

数据库查询追踪

// app/Providers/AppServiceProvider.phpnamespace App\Providers;use Illuminate\Support\ServiceProvider;
use OpenTracing\GlobalTracer;
use Illuminate\Support\Facades\DB;class AppServiceProvider extends ServiceProvider
{public function boot(){if (config('tracing.enabled', false)) {DB::listen(function ($query) {$tracer = GlobalTracer::get();$scope = $tracer->startActiveSpan('db.query', ['tags' => ['db.system' => 'mysql','db.statement' => $query->sql,'db.query.bindings' => json_encode($query->bindings),'db.query.time' => $query->time . 'ms',]]);$scope->close();});}}
}

HTTP 客户端追踪(Guzzle)

// app/Services/TracingHttpClient.phpnamespace App\Services;use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use OpenTracing\GlobalTracer;
use OpenTracing\Formats;
use OpenTracing\Tags;class TracingHttpClient
{public static function create(): Client{$stack = HandlerStack::create();$stack->push(self::createTracingMiddleware());return new Client(['handler' => $stack,'timeout' => 30,]);}private static function createTracingMiddleware(): callable{return function (callable $handler) {return function ($request, array $options) use ($handler) {$tracer = GlobalTracer::get();$scope = $tracer->startActiveSpan('http.client.request', ['tags' => [Tags\HTTP_METHOD => $request->getMethod(),Tags\HTTP_URL => (string) $request->getUri(),'http.target' => $request->getRequestTarget(),]]);// 注入追踪头$tracer->inject($scope->getSpan()->getContext(),Formats\HTTP_HEADERS,$request->getHeaders());return $handler($request, $options)->then(function ($response) use ($scope) {$scope->getSpan()->setTag(Tags\HTTP_STATUS_CODE, $response->getStatusCode());$scope->close();return $response;},function ($reason) use ($scope) {$scope->getSpan()->setTag(Tags\ERROR, true);$scope->getSpan()->log(['error' => $reason]);$scope->close();throw $reason;});};};}
}

队列任务追踪

// app/Jobs/TracedJob.phpnamespace App\Jobs;use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use OpenTracing\GlobalTracer;
use OpenTracing\Tags;class TracedJob implements ShouldQueue
{use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;protected $spanContext;public function __construct(array $spanContext = null){$this->spanContext = $spanContext;}public function handle(){$tracer = GlobalTracer::get();$scope = $tracer->startActiveSpan('job.process', ['child_of' => $this->spanContext,'tags' => ['job.name' => static::class,'job.queue' => $this->queue,'job.attempts' => $this->attempts(),]]);try {$this->processJob();$scope->close();} catch (\Exception $e) {$scope->getSpan()->setTag(Tags\ERROR, true);$scope->getSpan()->log(['event' => 'error','error.kind' => get_class($e),'message' => $e->getMessage(),]);$scope->close();throw $e;}}protected function processJob(){// 实际的作业处理逻辑}// 在分发作业时保存追踪上下文public static function dispatchWithTracing(){$tracer = GlobalTracer::get();$spanContext = $tracer->getActiveSpan()?->getContext();return new static($spanContext);}
}

配置文件

php artisan vendor:publish --provider="App\Providers\TracingServiceProvider"
// config/tracing.phpreturn ['enabled' => env('TRACING_ENABLED', true),'service_name' => env('TRACING_SERVICE_NAME', env('APP_NAME', 'laravel-app')),'jaeger' => ['agent_host' => env('JAEGER_AGENT_HOST', 'localhost'),'agent_port' => env('JAEGER_AGENT_PORT', 6831),],'sampler' => ['type' => env('TRACING_SAMPLER_TYPE', 'const'),'param' => env('TRACING_SAMPLER_PARAM', true),],'tags' => ['environment' => env('APP_ENV', 'production'),'version' => env('APP_VERSION', '1.0.0'),],
];

.env 配置

TRACING_ENABLED=true
TRACING_SERVICE_NAME=my-laravel-app
JAEGER_AGENT_HOST=localhost
JAEGER_AGENT_PORT=6831
TRACING_SAMPLER_TYPE=const
TRACING_SAMPLER_PARAM=true

http请求的使用示例

// 在控制器中使用
namespace App\Http\Controllers;use App\Services\TracingHttpClient;
use OpenTracing\GlobalTracer;
use OpenTracing\Tags;class UserController extends Controller
{public function show($id){$tracer = GlobalTracer::get();$scope = $tracer->startActiveSpan('user.controller.show', ['tags' => ['user.id' => $id,]]);try {// 调用外部服务$client = TracingHttpClient::create();$response = $client->get('https://api.example.com/users/' . $id);$user = json_decode($response->getBody(), true);$scope->getSpan()->log(['message' => 'User fetched successfully']);return response()->json($user);} catch (\Exception $e) {$scope->getSpan()->setTag(Tags\ERROR, true);$scope->getSpan()->log(['error' => $e->getMessage()]);throw $e;} finally {$scope->close();}}
}

http://www.dtcms.com/a/344295.html

相关文章:

  • OpenCV 图像边缘检测
  • 设计模式之装饰模式
  • 技术革新:再互动平台如何以全链路数字化重构防伪溯源生态
  • 泵站远程监控与自动化控制系统:智慧泵房设备的创新实践
  • RLHF的定义
  • 无人机延时模块技术难点解析
  • 数字安全隐形基石:随机数、熵源与DRBG核心解析与技术关联
  • Kubernetes 构建高可用、高性能 Redis 集群
  • 服务器硬件中的磁盘SSD与HDD性能区别,以及分别适用于什么业务?
  • 高性能、高实时、高安全:如何在飞凌嵌入式i.MX95xx核心板上同时实现?
  • C++ 循环:从入门到精通的深度解析
  • KubeBlocks for MSSQL 高可用实现
  • 云原生(Cloud Native)技术概述
  • 企业级大模型解决方案:架构、落地与代码实现​
  • LeetCode 分类刷题:34. 在排序数组中查找元素的第一个和最后一个位置
  • Unreal Engine APawn 与 ACharacter 比较
  • 开发避坑指南(31):Oracle 11g LISTAGG函数使用陷阱,缺失WITHIN子句解决方案
  • 如何优雅统计知识库文件个数与子集下不同文件夹文件个数
  • Vue3源码reactivity响应式篇之Ref
  • Oracle APEX 经典报表中的Checkbox
  • 期货Level2五档订单簿0.25秒级高频分时及日频历史行情数据使用指南
  • Docker 部署 MySQL 8.0 完整指南:从拉取镜像到配置远程访问
  • 高级SQL优化 | 告别 Hive 中 GROUP BY 的大 KEY 数据倾斜!PawSQL 自适应优化算法详解
  • MsSQL 函数,实现数字转换成人民币大写
  • IDEA基础配置优化指南(中英双版)
  • matlab中随机森林算法的实现
  • AI重塑职业教育:个性化学习计划提效率、VR实操模拟强技能,对接就业新路径
  • 在Excel和WPS表格中如何隐藏单元格的公式
  • 视觉语言对比学习的发展史:从CLIP、BLIP、BLIP2、InstructBLIP(含MiniGPT4的详解)
  • 一分钟了解六通道 CAN(FD) 集线器