開發環境:
php >= 5.6
linux環境 必須安裝thrift
omposer require opentracing/opentracing 1.0.0-beta5
composer require jukylin/jaeger-php v2.1.3
下面展示一個程序内和跨程序的通路
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiATN381dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5yMxQzM4EmZ5UWYyQjMzUTNyYzX0EzMwYTMyEzLcRDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
http代碼中分别請求了crm.ichunt.com,baidu.com;在通路了baidu.com嵌套了子span通路ichunt.com;接下來通路http2.php
http2代碼中 通路了ichunt.com和crm.ichunt.com
<?php
/*
* Copyright (c) 2019, The Jaeger Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
require_once './vendor/autoload.php';
use Jaeger\Config;
use GuzzleHttp\Client;
use OpenTracing\Formats;
use OpenTracing\Reference;
unset($_SERVER['argv']);
set_time_limit(0);
//init server span start
$config = Config::getInstance();
$config->gen128bit();
$config::$propagator = Jaeger\Constants\PROPAGATOR_JAEGER;
$tracer = $config->initTracer('example-php', '192.168.1.234:6831');
$injectTarget = [];
$spanContext = $tracer->extract(Formats\TEXT_MAP, $_SERVER);
echo sprintf("parent-spanContext %s <br>",print_r($spanContext,true));
if(!$spanContext){
$serverSpan = $tracer->startSpan('example HTTP');
}else{
$serverSpan = $tracer->startSpan('example HTTP', ['references' => [
Reference::create(Reference::FOLLOWS_FROM, $spanContext),
Reference::create(Reference::CHILD_OF, $spanContext)
]]);
}
$serverSpan->addBaggageItem("version", "1.8.9");
$serverSpan->setTag("serverSpan-key","serverSpan-value");
$tracer->inject($serverSpan->getContext(), Formats\TEXT_MAP, $_SERVER);
//init server span end
$clientTracer = $config->initTracer('HTTP');
//client span1 start
$injectTarget1 = [];
$spanContext1 = $clientTracer->extract(Formats\TEXT_MAP, $_SERVER);
echo sprintf("spanContext1 %s <br>",print_r($spanContext1,true));
$clientSpan1 = $clientTracer->startSpan('request1', ['child_of' => $spanContext1]);
$clientTracer->inject($clientSpan1->spanContext, Formats\TEXT_MAP, $injectTarget1);
$method = 'GET';
$url = 'http://baidu.com/';
$client = new Client();
$res = $client->request($method, $url,['headers' => $injectTarget1]);
$clientSpan1->setTag('http.status_code', 200);
$clientSpan1->setTag('http.method', 'GET');
$clientSpan1->setTag('http.url', $url);
$clientSpan1->addBaggageItem("event","event-HTTP1-value");
$clientSpan1->log(['message' => "HTTP1 ". $method .' '. $url .' end !']);
$clientSpan1->finish();
//client span1 end
//--------------------------------------------------------------------------------------------
//client span2 start
$injectTarget2 = [];
$spanContext2 = $clientTracer->extract(Formats\TEXT_MAP,$_SERVER);
echo sprintf("spanContext2 %s <br>",print_r($spanContext2,true));
$clientSpan2 = $clientTracer->startSpan('request2',['references' => [
Reference::create(Reference::FOLLOWS_FROM, $clientSpan1->spanContext),
Reference::create(Reference::CHILD_OF, $spanContext1)
]]);
$clientTracer->inject($clientSpan2->spanContext, Formats\TEXT_MAP, $injectTarget2);
$method = 'GET';
//$url = 'http://192.168.1.169:8088/http2.php';
$url = 'http://ichunt.com/';
$client = new Client();
$res = $client->request($method, $url, ['headers' => $injectTarget2]);
$clientSpan2->setTag('http.status_code', 200);
$clientSpan2->setTag('http.method', 'GET');
$clientSpan2->setTag('http.url', $url);
$clientSpan2->log(['message' => "HTTP2 ". $method .' '. $url .' end !']);
$clientSpan2->finish();
////client span2 end
//--------------------------------------------------------------------------------------------
//client span3 start
$injectTarget3 = [];
$spanContext3 = $clientTracer->extract(Formats\TEXT_MAP,$_SERVER);
echo sprintf("spanContext3 %s <br>",print_r($spanContext3,true));
$clientSpan3 = $clientTracer->startSpan('request3',
['references' => [
Reference::create(Reference::FOLLOWS_FROM, $spanContext3),
Reference::create(Reference::CHILD_OF, $spanContext3)
]]);
$clientTracer->inject($clientSpan3->spanContext, Formats\TEXT_MAP, $injectTarget3);
$method = 'GET';
$url = 'http://crm.ichunt.net/';
$client = new Client();
$res = $client->request($method, $url, ['headers' => $injectTarget3]);
$clientSpan3->setTag('http.status_code', 200);
$clientSpan3->setTag('http.method', 'GET');
$clientSpan3->setTag('http.url', $url);
$clientSpan3->log(['message' => "HTTP2 ". $method .' '. $url .' end !']);
$clientSpan3->finish();
////client span3 end
//--------------------------------------------------------------------------------------------
//client span2 start
$injectTarget4 = [];
$spanContext4 = $clientTracer->extract(Formats\TEXT_MAP, $_SERVER);
echo sprintf("spanContext4 %s <br>",print_r($spanContext4,true));
$clientSpan4 = $clientTracer->startSpan('request4',
['references' => [
Reference::create(Reference::FOLLOWS_FROM, $spanContext4),
Reference::create(Reference::CHILD_OF, $spanContext4)
]]);
$clientTracer->inject($clientSpan4->spanContext, Formats\TEXT_MAP, $injectTarget4);
$method = 'GET';
$url = 'http://192.168.1.169/http2.php';
$client = new Client();
$res = $client->request($method, $url, ['headers' => $injectTarget4]);
$clientSpan4->setTag('http.status_code', 200);
$clientSpan4->setTag('http.method', 'GET');
$clientSpan4->setTag('http.url', $url);
$clientSpan4->log(['message' => "HTTP2 ". $method .' '. $url .' end !']);
$clientSpan4->finish();
//client span2 end
////server span end
$serverSpan->finish();
//trace flush
$config->flush();
echo "success\r\n";
http.php
<?php
/*
* Copyright (c) 2019, The Jaeger Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
require_once './vendor/autoload.php';
use Jaeger\Config;
use GuzzleHttp\Client;
use OpenTracing\Formats;
use OpenTracing\Reference;
unset($_SERVER['argv']);
function getAllHeaders()
{
$headers = array();
$copy_server = array(
'CONTENT_TYPE' => 'Content-Type',
'CONTENT_LENGTH' => 'Content-Length',
'CONTENT_MD5' => 'Content-Md5',
);
foreach ($_SERVER as $key => $value) {
if (substr($key, 0, 5) === 'HTTP_') {
$key = substr($key, 5);
if (!isset($copy_server[$key]) || !isset($_SERVER[$key])) {
$key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key))));
$headers[$key] = $value;
}
} elseif (isset($copy_server[$key])) {
$headers[$copy_server[$key]] = $value;
}
}
if (!isset($headers['Authorization'])) {
if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
$headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
} elseif (isset($_SERVER['PHP_AUTH_USER'])) {
$basic_pass = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : '';
$headers['Authorization'] = 'Basic ' . base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $basic_pass);
} elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) {
$headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST'];
}
}
return $headers;
}
$config = Config::getInstance();
$config->gen128bit();
$config::$propagator = Jaeger\Constants\PROPAGATOR_JAEGER;
$tracer = $config->initTracer('http2-php', '192.168.1.234:6831');
$spanContext = $tracer->extract(Formats\TEXT_MAP, getAllHeaders());
if(!$spanContext){
$serverSpan = $tracer->startSpan('Istio2');
}else{
$serverSpan = $tracer->startSpan('Istio2', ['references' => [
Reference::create(Reference::FOLLOWS_FROM, $spanContext),
Reference::create(Reference::CHILD_OF, $spanContext)
]]);
}
$serverSpan->setTag("parent","parent-span");
$serverSpan->log(["parent"=>"parent-log"]);
$tracer->inject($serverSpan->getContext(), Formats\TEXT_MAP, $_SERVER);
$clientTracer = $config->initTracer('HTTP');
//-------------------------
$injectTarget2 = [];
$spanContext = $clientTracer->extract(Formats\TEXT_MAP, $_SERVER);
print_r($spanContext);
if(!$spanContext){
$clientSpan2 = $clientTracer->startSpan('request2');
}else{
$clientSpan2 = $clientTracer->startSpan('request2', ['references' => [
Reference::create(Reference::FOLLOWS_FROM, $serverSpan->spanContext),
Reference::create(Reference::CHILD_OF, $spanContext)
]]);
}
$clientTracer->inject($clientSpan2->spanContext, Formats\TEXT_MAP, $injectTarget2);
$method = 'GET';
$url = 'http://ichunt.com/';
$client = new Client();
$res = $client->request($method, $url, ['headers' => $injectTarget2]);
$clientSpan2->setTag('http.status_code', 200);
$clientSpan2->setTag('http.method', 'GET');
$clientSpan2->setTag('http.url', $url);
$clientSpan2->log(['message' => "HTTP2 ". $method .' '. $url .' end !']);
$clientSpan2->finish();
//---------------------------------------
//client span3 start
$injectTarget3 = [];
$spanContext3 = $clientTracer->extract(Formats\TEXT_MAP,$_SERVER);
print_r($spanContext3);
if(!$spanContext3){
$clientSpan3 = $clientTracer->startSpan('request3');
}else{
$clientSpan3 = $clientTracer->startSpan('request3',
['references' => [
Reference::create(Reference::FOLLOWS_FROM, $spanContext3),
Reference::create(Reference::CHILD_OF, $spanContext3)
]]);
}
$clientTracer->inject($clientSpan3->spanContext, Formats\TEXT_MAP, $injectTarget3);
$method = 'GET';
$url = 'http://crm.ichunt.net/';
$client = new Client();
$res = $client->request($method, $url, ['headers' => $injectTarget3]);
$clientSpan3->setTag('http.status_code', 200);
$clientSpan3->setTag('http.method', 'GET');
$clientSpan3->setTag('http.url', $url);
$clientSpan3->log(['message' => "HTTP2 ". $method .' '. $url .' end !']);
$clientSpan3->finish();
////client span3 end
////server span end
$serverSpan->finish();
//trace flush
$config->flush();
echo "success\r\n";
http2.php
對上面代碼進行封裝:
JaegerInject.php
<?phpnamespace Common\Service;
use Jaeger\Config as Jconfing;
use OpenTracing\Formats;
use OpenTracing\Reference;
class JaegerInject
{
protected $dsn = '192.168.1.234:6831';
protected $serviceName;
protected $spanList = [];
protected $client;
protected $tracer;
protected $clientTracer;
public function __construct($serviceName = 'opentarcing-php',$parentSpanName="")
{
$this->serviceName = $serviceName;
unset($_SERVER['argv']);
$this->client = Jconfing::getInstance();
Jconfing::$propagator = \Jaeger\Constants\PROPAGATOR_JAEGER;
$this->client->gen128bit();
$this->tracer = $this->client->initTracer($this->serviceName, $this->dsn);
$parentContext = $this->tracer->extract(Formats\TEXT_MAP, $this->getAllHeaders());
if (!$parentContext) {
$serverSpan = $this->tracer->startSpan($parentSpanName);
} else {
$serverSpan = $this->tracer->startSpan($parentSpanName, ['references' => [
Reference::create(Reference::FOLLOWS_FROM, $parentContext),
Reference::create(Reference::CHILD_OF, $parentContext)
]]);
}
$serverSpan->setTag("parent","123");
$this->tracer->inject($serverSpan->getContext(),Formats\TEXT_MAP, $_SERVER);
$this->clientTracer = $this->client->initTracer('HTTP');
$this->spanList[$parentSpanName]=[
"current_span"=>$serverSpan,
"parent_context"=>$parentContext
];
}
public function getSpanName($spanName){
return isset($this->spanList[$spanName]) ? $this->spanList[$spanName]["current_span"] : "";
}
public function setTag($spanName,$key="",$value=""){
if(!isset($this->spanList[$spanName])){
return ;
}
$info = $this->spanList[$spanName];
$span = $info['current_span'];
$span->setTag($key,$value);
}
public function log($spanName,$key="",$value=""){
if(!isset($this->spanList[$spanName])){
return ;
}
$info = $this->spanList[$spanName];
$span = $info['current_span'];
$span->log([$key=>$value]);
}
public function start($spanName,$parentSpan="")
{
$spanContext = $this->clientTracer->extract(Formats\TEXT_MAP, $_SERVER);
$clientrSpan = null;
$parentSpanIsObj = $parentSpan && gettype($parentSpan) == "object";
if (!$spanContext) {
$clientrSpan = $this->tracer->startSpan($spanName);
} else {
$clientrSpan = $this->tracer->startSpan($spanName, ['references' => [
Reference::create(Reference::FOLLOWS_FROM, $parentSpanIsObj ? $parentSpan->spanContext :$spanContext),
Reference::create(Reference::CHILD_OF, $spanContext)
]]);
}
$this->spanList[$spanName]=[
"current_span"=>$clientrSpan,
"parent_context"=>$parentSpanIsObj ? $parentSpan->spanContext :$spanContext,
];
}
public function inject($spanName)
{
$info = $this->spanList[$spanName];
$span = $info['current_span'];
$injectHeaders = [];
$this->clientTracer->inject($span->getContext(), Formats\TEXT_MAP, $injectHeaders);
return $injectHeaders;
}
public function finish( $spanName, array $spanList = [])
{
$info = $this->spanList[$spanName];
$span = $info['current_span'];
$parentContext = $info['parent_context'];
$span->setTag('parentSpan', $parentContext ? $parentContext->spanIdToString() : '');
foreach($spanList ?: [] as $k => $v){
$span->setTag($k, $v);
}
$span->finish();
}
private function getAllHeaders()
{
$headers = array();
$copy_server = array(
'CONTENT_TYPE' => 'Content-Type',
'CONTENT_LENGTH' => 'Content-Length',
'CONTENT_MD5' => 'Content-Md5',
);
foreach ($_SERVER as $key => $value) {
if (substr($key, 0, 5) === 'HTTP_') {
$key = substr($key, 5);
if (!isset($copy_server[$key]) || !isset($_SERVER[$key])) {
$key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key))));
$headers[$key] = $value;
}
} elseif (isset($copy_server[$key])) {
$headers[$copy_server[$key]] = $value;
}
}
if (!isset($headers['Authorization'])) {
if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
$headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
} elseif (isset($_SERVER['PHP_AUTH_USER'])) {
$basic_pass = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : '';
$headers['Authorization'] = 'Basic ' . base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $basic_pass);
} elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) {
$headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST'];
}
}
return $headers;
}
public function __destruct()
{
$this->client->flush();
}
}
public function opentarcing_one(){
$jaeger = new \Common\Service\JaegerInject("opentarcing-php","opentarcing_one");
$jaeger->setTag("opentarcing_one","事件","建立訂單");
$jaeger->log("opentarcing_one","請求參數",json_encode(cookie()));
$spanName = "order-admin";
$jaeger->start($spanName);
$injectHeaders = $jaeger->inject($spanName);
$client = new \GuzzleHttp\Client;
$method = 'GET';
$url = 'http://crm.ichunt.net/';
$res = $client->request($method, $url, ['headers' => $injectHeaders]);
$jaeger->finish($spanName, ['time' => date('Y-m-d H:i:s')]);
$spanName = "ichunt-api";
$jaeger->start($spanName);
$injectHeaders = $jaeger->inject($spanName);
$client = new \GuzzleHttp\Client;
$method = 'GET';
$url = 'http://order.ichunt.net/';
$res = $client->request($method, $url, ['headers' => $injectHeaders]);
$jaeger->finish($spanName, ['time' => date('Y-m-d H:i:s')]);
//--------------crm.net-----下包含子span---crm.child.net------------------------------
$spanName = "crm.net";
$jaeger->start($spanName);
$injectHeaders = $jaeger->inject($spanName);
$client = new \GuzzleHttp\Client;
$method = 'GET';
$url = 'http://label.ichunt.net/';
$res = $client->request($method, $url, ['headers' => $injectHeaders]);
$jaeger->finish($spanName, ['time' => date('Y-m-d H:i:s')]);
$spanName = "crm.child.net";
$parentSpanName = $jaeger->getSpanName("crm.net");
$jaeger->start($spanName,$parentSpanName);
$injectHeaders = $jaeger->inject($spanName);
$client = new \GuzzleHttp\Client;
$method = 'GET';
$url = 'http://crm.ichunt.net/';
$res = $client->request($method, $url, ['headers' => $injectHeaders]);
$jaeger->finish($spanName, ['time' => date('Y-m-d H:i:s')]);
//----------------crm.net-----下包含子span---crm.child.net-------------------------------
$spanName = "跨程序通路http2.php";
$jaeger->start($spanName);
$injectHeaders = $jaeger->inject($spanName);
$client = new \GuzzleHttp\Client;
$method = 'GET';
$url = 'http://api.liexin.com/order/test/opentarcing_two';
$jar = new \GuzzleHttp\Cookie\CookieJar();
$cookieJar = $jar->fromArray(cookie(), "liexin.com");
$res = $client->request($method, $url, ['headers' => $injectHeaders,"cookies"=>$cookieJar]);
// dump(cookie());
// $res = post_curl($url,[],$injectHeaders);
$jaeger->finish($spanName, ['time' => date('Y-m-d H:i:s')]);
}
public function opentarcing_two()
{
$jaeger = new \Common\Service\JaegerInject("opentarcing-php","opentarcing_two");
$spanName = "crm.net";
$jaeger->start($spanName);
$injectHeaders = $jaeger->inject($spanName);
$client = new \GuzzleHttp\Client;
$method = 'GET';
$url = 'http://label.ichunt.net/';
$res = $client->request($method, $url, ['headers' => $injectHeaders]);
$jaeger->finish($spanName, ['time' => date('Y-m-d H:i:s')]);
$spanName = "crm.child.net";
$parentSpanName = $jaeger->getSpanName("crm.net");
$jaeger->start($spanName,$parentSpanName);
$injectHeaders = $jaeger->inject($spanName);
$client = new \GuzzleHttp\Client;
$method = 'GET';
$url = 'http://crm.ichunt.net/';
$res = $client->request($method, $url, ['headers' => $injectHeaders]);
$jaeger->finish($spanName, ['time' => date('Y-m-d H:i:s')]);
}
生産場景使用後優化代碼
上述代碼在生産實踐中發現每次執行個體化一個JaegerInject對象就會建立一個udp請求;
優化目的:一次請求建立一次udp請求
建議:使用中盡量能使用同一個JaegerInject對象
checkPhpUname方法 為了防止windows電腦上無法運作thirft
/*
* 判斷運作環境是否是linux
*/
function checkPhpUname(){
$os_name = PHP_OS;
if(strpos($os_name,"Linux")!==false){
return true;
}else{
return false;
}
}
<?php
namespace Common\Service;
use Jaeger\Config as Jconfing;
use OpenTracing\Formats;
use OpenTracing\Reference;
class JaegerInject
{
protected $dsn = '192.168.1.234:6831';
protected $serviceName;
public static $spanList = [];
protected $client;
protected $tracer;
protected $clientTracer;
protected $uname;//開發環境 window mac linux
public static $parentSpanName = null;
public static $instance = null;
private function __construct(){
}
private function __clone(){
}
public static function getInstance()
{
if(! (self::$instance instanceof self) )
{
self::$instance = new self();
}
return self::$instance;
}
protected function getClientIp()
{
$ip = '0.0.0.0';
if (getenv('HTTP_CLIENT_IP')) {
$ip = getenv('HTTP_CLIENT_IP');
}
if (getenv('HTTP_X_REAL_IP')) {
$ip = getenv('HTTP_X_REAL_IP');
} elseif (getenv('HTTP_X_FORWARDED_FOR')) {
$ip = getenv('HTTP_X_FORWARDED_FOR');
$ips = explode(',', $ip);
$ip = $ips[0];
} elseif (getenv('REMOTE_ADDR')) {
$ip = getenv('REMOTE_ADDR');
}
return $ip;
}
public function getSpanName($spanName){
if(!$this->uname){
return "";
}
return isset(static::$spanList[$spanName]) ? static::$spanList[$spanName]["current_span"] : "";
}
public function setTag($spanName,$key="",$value=""){
if(!$this->uname){
return "";
}
if(!isset(static::$spanList[$spanName])){
return ;
}
$info = static::$spanList[$spanName];
$span = $info['current_span'];
$span->setTag($key,$value);
}
/*
* 記錄鍊路追蹤日志
*/
public function log($spanName,$key="",$value=""){
if(!$this->uname){
return "";
}
if(!isset(static::$spanList[$spanName])){
return ;
}
$info = static::$spanList[$spanName];
$span = $info['current_span'];
if($key && $value){
$span->log([$key=>$value]);
}else if($key && !$value){
$span->log(["message"=>$key]);
}
}
/*
* 創建父span
*/
public function init($parentSpanName=""){
$this->serviceName = C("OPENTRACING_JAEGER_SERVERNAME");
$this->client = Jconfing::getInstance();
Jconfing::$propagator = \Jaeger\Constants\PROPAGATOR_JAEGER;
$this->client->gen128bit();
$this->tracer = $this->client->initTracer($this->serviceName, C("OPENTRACING_JAEGER_DNS"));
if(!static::$parentSpanName && !$parentSpanName){
static::$parentSpanName = "未知的spanName";
if(isset($_SERVER['REQUEST_URI']) && $_SERVER['REQUEST_URI']){
$requestUrl = explode("?",$_SERVER['REQUEST_URI']);
static::$parentSpanName = !empty($requestUrl) ? $requestUrl[0] : static::$parentSpanName;
}
}
if($parentSpanName && !static::$parentSpanName){
static::$parentSpanName = $parentSpanName;
}
if(!isset(static::$spanList[static::$parentSpanName])) {
if(!checkPhpUname()){
$this->uname = false;
return ;
}else{
$this->uname = true;
}
$this->startPrentSpan();
}
}
public function simpleInit($parentSpanName="",$spanName=""){
$this->init($parentSpanName);
$this->start($spanName);
$injectHeaders = $this->inject($spanName);
return $injectHeaders;
}
public function simpleInject($spanName,$preSpanName=""){
if($preSpanName){
$preSpanName = $this->getSpanName($preSpanName);
}
$this->start($spanName,$preSpanName);
$injectHeaders = $this->inject($spanName);
return $injectHeaders;
}
protected function startPrentSpan(){
$parentSpanName = static::$parentSpanName;
$parentContext = $this->tracer->extract(Formats\TEXT_MAP, $this->getAllHeaders());
// dump($parentContext);
if (!$parentContext) {
$serverSpan = $this->tracer->startSpan($parentSpanName);
} else {
$serverSpan = $this->tracer->startSpan($parentSpanName, ['references' => [
Reference::create(Reference::FOLLOWS_FROM, $parentContext),
Reference::create(Reference::CHILD_OF, $parentContext)
]]);
}
$serverSpan->setTag("http_host",$this->getClientIp());
$serverSpan->setTag("time",date("Y-m-d H:i:s"));
if(isset($_SERVER['REQUEST_SCHEME'])){
$serverSpan->setTag("request_scheme",$_SERVER['REQUEST_SCHEME']);
}
if(isset($_SERVER['REQUEST_URI'])){
$serverSpan->setTag("request_uri",$_SERVER['REQUEST_URI']);
}
if(!empty($_REQUEST)){
$serverSpan->log(["request_params"=>json_encode($_REQUEST)]);
}
$this->tracer->inject($serverSpan->getContext(),Formats\TEXT_MAP, $_SERVER);
$this->clientTracer = $this->client->initTracer('HTTP');
static::$spanList[$parentSpanName]=[
"current_span"=>$serverSpan,
"parent_context"=>$parentContext
];
}
/*
* 創建子span
*/
public function start($spanName,$parentSpan="")
{
if(!$this->uname){
return ;
}
$spanContext = $this->clientTracer->extract(Formats\TEXT_MAP, $_SERVER);
$clientrSpan = null;
$parentSpanIsObj = $parentSpan && gettype($parentSpan) == "object";
if (!$spanContext) {
$clientrSpan = $this->tracer->startSpan($spanName);
} else {
$clientrSpan = $this->tracer->startSpan($spanName, ['references' => [
Reference::create(Reference::FOLLOWS_FROM, $parentSpanIsObj ? $parentSpan->spanContext :$spanContext),
Reference::create(Reference::CHILD_OF, $spanContext)
]]);
}
static::$spanList[$spanName]=[
"current_span"=>$clientrSpan,
"parent_context"=>$parentSpanIsObj ? $parentSpan->spanContext :$spanContext,
];
}
public function inject($spanName)
{
if(!$this->uname){
return [];
}
if(!isset(static::$spanList[$spanName])){
return [];
}
$info = static::$spanList[$spanName];
$span = $info['current_span'];
$injectHeaders = [];
$this->clientTracer->inject($span->getContext(), Formats\TEXT_MAP, $injectHeaders);
return $injectHeaders;
}
public function finish( $spanName, array $spanList = [])
{
if(!$this->uname){
return;
}
if(!isset(static::$spanList[$spanName])){
return;
}
$info = static::$spanList[$spanName];
$span = $info['current_span'];
$parentContext = $info['parent_context'];
$span->setTag('parentSpan', $parentContext ? $parentContext->spanIdToString() : '');
$span->setTag("time",date("Y-m-d H:i:s"));
foreach($spanList ?: [] as $k => $v){
$span->setTag($k, $v);
}
$span->finish();
}
private function getAllHeaders()
{
$headers = array();
$copy_server = array(
'CONTENT_TYPE' => 'Content-Type',
'CONTENT_LENGTH' => 'Content-Length',
'CONTENT_MD5' => 'Content-Md5',
);
foreach ($_SERVER as $key => $value) {
if (substr($key, 0, 5) === 'HTTP_') {
$key = substr($key, 5);
if (!isset($copy_server[$key]) || !isset($_SERVER[$key])) {
$key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key))));
$headers[$key] = $value;
}
} elseif (isset($copy_server[$key])) {
$headers[$copy_server[$key]] = $value;
}
}
if(isset($_SERVER["UBER-TRACE-ID"])){
$headers["UBER-TRACE-ID"] = $_SERVER["UBER-TRACE-ID"];
}
if (!isset($headers['Authorization'])) {
if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
$headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
} elseif (isset($_SERVER['PHP_AUTH_USER'])) {
$basic_pass = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : '';
$headers['Authorization'] = 'Basic ' . base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $basic_pass);
} elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) {
$headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST'];
}
}
return $headers;
}
public function __destruct()
{
if(!$this->uname){
return ;
}
$this->client->flush();
}
}
JaegerInject
$this->opentracingJager = \Common\Service\JaegerInject::getInstance();
//頂級span
$this->opentracingJager->init("pay");
//....項目代碼.........
//添加tag标簽
$this->opentracingJager->setTag("pay","action","returnUrl");
$this->opentracingJager->setTag("pay","remark",sprintf("--支付同步回調--"));
//....項目代碼.........
//添加日志
$this->opentracingJager->log("pay",sprintf("支付、充值同步回調異常:%s",json_encode($res)));
//....項目代碼.........
//添加兄弟層span
$this->opentracingJager->simpleInject("payment");
$this->opentracingJager->log("payment","Pay->response()傳回的資料",sprintf("%s",json_encode($arr)));
//....項目代碼.........
$this->opentracingJager->finish("payment");
//....項目代碼.........
$this->opentracingJager->finish("pay");
//添加一個子span
//上述代碼中如果需要在payment span下面添加子節點
$this->opentracingJager->init("xxx");
//$jaeger->simpleInject("xxx","父span名字");
$jaeger->simpleInject("xxx","payment");
//添加tag标簽
$this->opentracingJager->setTag("xxx","action","123");
$this->opentracingJager->setTag("xxx","remark",sprintf("--支付同步回調--"));
//添加日志
$this->opentracingJager->log("xxx",sprintf("支付、充值同步回調異常:%s",json_encode($res)));
//....項目代碼.........
$this->opentracingJager->finish("xxx");