Skip to content

masixun71/swoft-jaeger

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

简介

本项目属于swoft的jaeger client,非侵入式地对项目环境进行跟踪并且异步上报到jaeger server,可以和其他的swoft项目或者其他语言(java,go)进行全链路监控,能监控mysql,redis,httpClient的正常异常情况。并且上传是使用thrift,udp 上传,效率较高。 目前新版本(v0.0.0.7以上)支持log记录,不使用udp,提高效率

之前我还写过zipkin的sdk,链接如下swoft-zipkin

环境要求

1.扩展要求

  • sockets ,因为上传需要用到udp传输,所以需要该扩展

配置步骤

1.composer

       "minimum-stability": "dev",
	   "prefer-stable": true,

先给composer.json添加如下语句,因为我们项目里引入的opentracing/opentracing官方最新的也只是一个beta包,不加会导致无法引入

composer require extraswoft/jaeger

引入本项目的包

2.config/properties/app.php 添加

需要在app文件,beanScan里加上扫描我们的命名空间

      'beanScan' => [
		"ExtraSwoft\\Jaeger\\",
    ],

3.config/beans/base.php添加我们的中间件

    'serverDispatcher' => [
        'middlewares' => [
            \Swoft\View\Middleware\ViewMiddleware::class,
			JaegerMiddleware::class,
//             \Swoft\Devtool\Middleware\DevToolMiddleware::class,
            // \Swoft\Session\Middleware\SessionMiddleware::class,
        ]
    ],

4.在.env配置文件中添加以下配置

ZIPKIN_HOST: jager_client 的地址
ZIPKIN_RAND: 采样率,1为100%, 最小可设为0.0001,线上环境建议采样
ENV: 配置环境,通过配置环境可以共用一个jaegerServer
JAEGER_OPEN: 是否开启jaeger,可不同环境不同配置
JAEGER_MODE: 1:使用udp传输,2:写入日志,日志依赖 @log 的配置(小时区分日志)
 #jaeger
JAEGER_RATE=1
JAEGER_SERVER_HOST=172.21.134.20:6831
JAEGER_OPEN=true
JAEGER_MODE=2
ENV=test

5.httpClient 的修改

当我们使用swoft官方的httpClient的时候,需要使用我们客户端的adapter,挂上钩子

$client = new Client(['adapter' => new AddJaegerAdapter()]);

当然,你也可以看下我们适配器的源码放到自己的适配器里,比较简单

源码修改

因为在mysql,redis和http的请求上没有钩子函数,所以我们需要自己实现,只要在请求开始和结束加上事件触发即可。建议自己或者公司项目直接fork官方的swoft-component,然后根据自己需要开发,并且隔一段时间同步最新代码,在swoft里面composer使用component这个仓库。

1.mysql(协程)

src/db/src/Db.php中,在$connection->prepare($sql);前添加(注意命名空间加入)

         Log::profileStart($profileKey);
+        App::trigger('Mysql', 'start', $profileKey, $sql);
         $connection->prepare($sql);
         $params = self::transferParams($params);
         $result = $connection->execute($params);

src/db/src/DbCoResult.php中,在Log::profileEnd($this->profileKey);后添加(注意命名空间加入)

         $this->release();

         Log::profileEnd($this->profileKey);
+        App::trigger('Mysql', 'end', $this->profileKey, true);
         return $result;

2.redis (非协程),协程可以根据自己需要添加

src/redis/src/Redis.php(注意命名空间加入)

在 $result = $connection->$method(...$params);前后添加

         $connectPool = App::getPool($this->poolName);
         /* @var ConnectionInterface $client */
         $connection = $connectPool->getConnection();
+        App::trigger('Redis', 'start', $method, $params);
         $result     = $connection->$method(...$params);
         $connection->release(true);
+        App::trigger('Redis', 'end', true);

         return $result;

3.httpClient (协程)

src/http-client/src/Adapter/CoroutineAdapter.php

在 $client->execute($path);前添加

 if ($query !== '') $path .= '?' . $query;

         $client->setDefer();
+        App::trigger('HttpClient', 'start', $request, $options);
         $client->execute($path);

         App::profileEnd($profileKey);

src/http-client/src/HttpCoResult.php

在 得到$response后添加

         $response = $this->createResponse()
            ->withBody(new SwooleStream($result ?? ''))
            ->withHeaders($headers ?? [])
            ->withStatus($this->deduceStatusCode($client));
        App::trigger('HttpClient', 'end', $response);

        return $response;

捕获异常

在全局的SwoftExceptionHandler.php里面添加对MysqlExceptionRedisException异常的钩子,保证我们能把异常的情况也上报了

else if ($throwable instanceof MysqlException) {
        App::trigger('Mysql', 'end', 'all', false, $throwable->getMessage());
} else if ($throwable instanceof RedisException) {
        App::trigger('Redis', 'end' , false, $throwable->getMessage());
}

完成

完成以上修改后,重新composer引入新的swoft-component包,然后重启项目就可以了

log记录

新版本支持将数据写入log,但由于原生字符串包含换行符,导致写入日志变成多行而不是一行,所以在写入日志时 会特殊处理, 变为: 'jaegerMsg:' . urlencode($thriftFile) . "\n"

获取header

因为链路传递是通过header来服务的,所以项目里面当有特殊的client时,想要获取header来传递可以使用下面方法

\Swoft::getBean(TracerManager::class)->getHeader();

Jaeger 的搭建

我把我的搭建心得都放在了下面这篇文章里面了 全链路监控Jaeger搭建实战

但是如果你懒得看,也可以直接用下面的

docker run -d -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 -p5775:5775/udp -p6831:6831/udp -p6832:6832/udp \
  -p5778:5778 -p16686:16686 -p14268:14268 -p9411:9411 jaegertracing/all-in-one:latest

直接起就搭建完成了,默认client 接受端口是6831

效果图

jaegerUI.png

About

swoft jaeger sdk

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages