diff --git a/README.md b/README.md index d168fa2ebb10bc50488bc2b22de8ba5867014584..88e0a791b38764b043f7a8d3dec67eb53820af7f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Sky Walking for php SDK| [中文](README_ZH.md) ========== **SkyWalking php SDK**: A client tool developed for PHP using SkyWalking APM tools. (It is a pity that it only supports writing log and checking curl currently.) -SkyWalking APM : https://github.com/OpenSkywalking/skywalking +SkyWalking APM : https://github.com/apache/incubator-skywalking * Automatic probe for PHP. **You don't need to modify the application code.** * It is a PHP extension developed by zendAPI. @@ -20,7 +20,7 @@ SkyWalking APM : https://github.com/OpenSkywalking/skywalking # Apply to * version 1.0 applies to Skywalking 3.1 . - +* version 2.0 applies to Skywalking 3.X . # In the future. * more php versions. * more os. diff --git a/README_ZH.md b/README_ZH.md index 3d29118b1d8ce924bc69bd79a69ef76064fce977..4f94b9e7dc3a66aba6edd22bb8c623aa48d2ccc1 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -3,7 +3,7 @@ Sky Walking SDK for PHP | [English](README.md) **SkyWalking php SDK**: 针对SkyWalking APM工具为php开发的客户端工具 (目前只支持写日志方式和只针对curl检测) -SkyWalking APM : https://github.com/OpenSkywalking/skywalking +SkyWalking APM : https://github.com/apache/incubator-skywalking * PHP 自动探针 **不需要修改应用程序代码** * 使用zendAPI开发的 php扩展 @@ -17,12 +17,12 @@ SkyWalking APM : https://github.com/OpenSkywalking/skywalking # 使用安装 -* php扩展包(https://github.com/SkywalkingContrib/skywalking-php-sdk/tree/songzhian/sky-php7ext) -* php代码类包(https://github.com/SkywalkingContrib/skywalking-php-sdk/tree/songzhian/sdk-php) +* php扩展包(https://github.com/SkywalkingContrib/skywalking-php-sdk/blob/songzhian/sky-php7ext/README_ZH.md) +* php代码类包(https://github.com/SkywalkingContrib/skywalking-php-sdk/blob/songzhian/sdk-php/README_ZH.md) # 对应版本支持 * 1.0对应版本:Skywalking 3.1 - +* 2.0对应版本:Skywalking 3.x # 将要完成 * 其它php版本扩展支持 * 更多系统支持 diff --git a/sdk-php/README_ZH.md b/sdk-php/README_ZH.md new file mode 100644 index 0000000000000000000000000000000000000000..bf772d42bdfd90565bb44702771622bb44173edf --- /dev/null +++ b/sdk-php/README_ZH.md @@ -0,0 +1,51 @@ +# PHP SkyWalking : SkyWalking PHP ͻ + + +--- + +- [װ](#installation) +- [Ҫ](#requirements) +- [ٿʼʵ](#quick-start-and-examples) + +--- + +### Installation + +ʹðװ SkyWalking , : + + +### Requirements + +PHP Curl Class works with PHP 5.2 - 7.9.99 , and HHVM. + +### Quick Start and Examples + + // must put these code at the beginning !!! + // that would auto register shutdown function !!! + + include_once ("./sdk-php/SkyWalking.php");// or use composer + + //LOG_PATH is skywalking's logfile path + SkyWalking::getInstance("api")->setLogPath(LOG_PATH)->setSamplingRate(5); + + .... + .... + + $ch = curl_init(); + curl_setopt($ch); + + .... + .... + + SkyWalking::getInstance()->startSpanOfCurl("www.api.com", $headers); + + .... + .... + + curl_setopt($ch); + $rs = curl_exec($ch); + + SkyWalking::getInstance()->endSpanOfcurl($ch); + + .... + .... \ No newline at end of file diff --git a/sdk-php/SkyWalking.php b/sdk-php/SkyWalking.php index f7cb55cfe30a34e72b609dcd138eb0c6f1ce3ac8..75f56562bbb176b272f7a2d2aa5b4bb4076ac8c6 100644 --- a/sdk-php/SkyWalking.php +++ b/sdk-php/SkyWalking.php @@ -3,6 +3,7 @@ /** * Class SkyWalking * 需要 设置 LOG_PATH 常量 默认会放到/tmp/目录下 + * 需要设置registerUrl 注册apm项 默认 appinfo.mservice.m.api:8080 * * @package SkyWalking */ @@ -13,13 +14,12 @@ class SkyWalking * @var new self */ private static $_instance = null; - - /** * 当前应用系统名称 * @var $_appCode */ private static $_appCode = null; + /** * SkyWalking 包含的头信息 * @var array @@ -42,6 +42,10 @@ class SkyWalking * @var array */ private $_allNodeData = array(); + /** + * 总段节点数据 + */ + private $_allSegment = array(); /** * 父节点数据 * @var array @@ -57,13 +61,26 @@ class SkyWalking * @var array */ private $_spanFirstNodeData = array(); + /** + * appid 相关信息 + * @var array + */ + private $_appIds = array(); + /** * 生产的SPAN_ID * @var */ private $_spanID = 0; + /** + * 日志目录 + * @var unknown + */ private $_logPath; - + /** + * apm注册地址 + */ + private $_registerUrl; /** * 采样率,默认为100% * @var int @@ -77,100 +94,125 @@ class SkyWalking * 本次进程是否采样 */ private $_isSampling = null; + /** + * 关闭所有功能 + */ + private $_isClose = 0; /** * 定义替换简单字符常量 */ - const TRACEID = 'ts'; //TraceId - const STARTTIME = 'st'; //开始时间 - const ENDTIME = 'et'; //结束时间 - const APP_CODE = 'ac'; // App Code + const SEGMENT = 'sg'; //全部段节点 + const DISTRIBUTED_TRACEIDS = 'gt';//DistributedTraceIds + const TRACE_SEGMENT_ID = 'ts';//本次请求id + const APPLICATION_ID = 'ai';//app id + const APPLICATION_INSTANCE_ID = 'ii';//实例id const FATHER_NODE_DATA = 'rs'; //父节点数据 const SPANS_NODE_DATA = 'ss'; //span节点数据集合 - const DISTRIBUTED_TRACEIDS = 'gt';//DistributedTraceIds + + const PARENT_TRACE_SEGMENT_ID = "ts"; //本次请求id + const PARENT_APPLICATION_ID = "ai";//app id + const PARENT_SPAN_ID = "si";//spanid + const PARENT_SERVICE_ID = "vi";// + const PARENT_SERVICE_NAME = "vn"; + const NETWORK_ADDRESS_ID = "ni"; + const NETWORK_ADDRESS = "nn"; + const ENTRY_APPLICATION_INSTANCE_ID = "ea"; + const ENTRY_SERVICE_ID = "ei"; + const ENTRY_SERVICE_NAME = "en"; + const REF_TYPE_VALUE = "rv"; + const SPAN_ID = 'si'; //SpanId - const PEERHOST = 'ph'; //PeerHost + const SPAN_TYPE_VALUE = 'tv'; + const SPAN_LAYER_VALUE = "lv"; const FATHER_SPAN_ID = 'ps'; //父节点传过来的SpanId - const SPAN_SERVER_URI = 'on';// Span 的服务URI - const SPAN_STRING_PARAM = 'ts';//Span 的字符串型参数 - const SPAN_BOOL_PARAM = 'tb';//Span 的字符串型参数 - const SPAN_INT_PARAM = 'ti';//Span 的字符串型参数 - const SPAN_LOG = 'lo'; //Span 的日志 - + const STARTTIME = 'st'; //开始时间 + const ENDTIME = 'et'; //结束时间 + const COMPONENT_ID = 'ci'; + const COMPONENT_NAME = 'cn'; + const OPERATION_NAME_ID = 'oi'; + const OPERATION_NAME = 'on';// Span 的服务URI + const PEER_ID = 'pi'; + const PEER = 'pn'; + const IS_ERROR = 'ie'; + const TAGS = 'to'; + const LOGS = 'lo'; + + const KEY = "k"; + const VALUE = "v"; + + const TIME = "ti"; + const LOG_DATA = "ld"; + + /** + * 值设置常量 + */ + const IS_ARRAY = true; + const DEFAULT_REGISTER_URL = 'http://apm.api:12800'; + /** * 全部节点结构 + * @var array + */ + private static $_allNodesStruct = array( + self::DISTRIBUTED_TRACEIDS => null, + self::SEGMENT => null, + ); + + /** + * 全部段节点结构 * - * TRACEID["ts": "Segment.1490097253214.-866187727.57515.1.1"], --TraceId - * STARTTIME["st": 1490097253198], --开始时间,整个节点处理前的时间点 - * ENDTIME["et": "1494965637898"], --结束时间,整个节点处理完的时间点 - * FATHER_NODE_DATA["rs": [......]] --父节点 - * SPANS_NODE_DATA["ss": [......]] --span节点 - * APP_CODE["ac": [......]] --App Code - * DISTRIBUTED_TRACEIDS["ss": [......]] --父节点传过来的DistributedTraceIds,如果没有父节点则再创建一个TraceId当做DistributedTraceIds * @var array */ - private static $_allPartsNodesStruct = array + private static $_allSegmentStruct = array ( - self::TRACEID => null,//TraceId - self::STARTTIME => null,//总开始时间 - self::ENDTIME => null,//总结束时间 - self::FATHER_NODE_DATA => array(),//父节点数据 - self::SPANS_NODE_DATA => array(),//span节点数据集合 - self::APP_CODE => null,//span节点数据集合 - self::DISTRIBUTED_TRACEIDS => null,//DistributedTraceIds + self::TRACE_SEGMENT_ID => array(),//请求的 id + self::APPLICATION_ID => null,//appid + self::APPLICATION_INSTANCE_ID => null,//实力id + self::FATHER_NODE_DATA => array(),//父节点数据 + self::SPANS_NODE_DATA => array(),//span节点数据集合 ); /** * 父节点数据结构 * 数据格式 - * "rs": [父节点 - * ["ts": "parent_trace_0"], --父节点,传给本子节点的TraceId - * ["si": 1], --父节点,传给本子节点的SpanId - * ["ac": "REMOTE_APP"], --父节点,传给本子节点的App Code - * ["ph": "10.2.3.16:8080"] --父节点,传给本子节点的PeerHost - * ] * @var array */ private static $_fatherNodesStruct = array( - self::TRACEID => null,//父节点,传给本子节点的TraceId - self::SPAN_ID => null,//父节点,传给本子节点的SpanId - self::APP_CODE => null,//父节点,传给本子节点的App Code - self::PEERHOST => null,//父节点,传给本子节点的PeerHost + self::PARENT_TRACE_SEGMENT_ID => array(),//父节点,传给本子节点的TraceId + self::PARENT_APPLICATION_ID => null, + self::PARENT_SPAN_ID => null, + self::PARENT_SERVICE_ID => null, + self::PARENT_SERVICE_NAME => null, + self::NETWORK_ADDRESS_ID => null, + self::NETWORK_ADDRESS => null, + self::ENTRY_APPLICATION_INSTANCE_ID => null, + self::ENTRY_SERVICE_ID => null, + self::ENTRY_SERVICE_NAME => null, + self::REF_TYPE_VALUE => null, ); /** * span节点结构 * 数据格式 - * [ - * ["si": 1], --Span A的SpanId - * ["ps": -1], --父节点传过来的SpanId - * ["st": 1490097253228], --Span A的开始时间,创建Span A时设置 - * ["et": 1494965637898] --Span A的结束时间,Span A处理完时设置 - * ["on": "/serviceA"], --Span A的服务URI - * ["ts": --Span A的字符串型参数 - * ["span.layer": "http"] --Span A的协议,分为http、rpc、db - * ["component": "Tomcat"] --Span A的节点组件,如Tomcat、Nginx、HttpClient、DbClient - * ["peer.host": "127.0.0.1"] --Span A的请求源IP - * ["span.kind": "server"] --Span A的节点组件类型,分为server、client - * ["url": "10.2.3.16:8080/serviceA"] --Span A的访问地址URL - * ], - * ["tb": []], --Span A的布尔值型参数 - * ["ti": [ --Span A的整数值型参数 - * "peer.port": 80 --Span A的请求源Port - * ]], - * ["lo": []] --Span A的日志 - * ] * @var array */ private static $_spanNodeDataStruct = array( + self::SPAN_ID => '',//SpanId - self::FATHER_SPAN_ID => -1,//父节点传过来的SpanId - self::STARTTIME => '',//开始时间 - self::ENDTIME => '',//结束时间 - self::SPAN_SERVER_URI => '',// Span 的服务URI - self::SPAN_STRING_PARAM => array(),//Span 的字符串型参数 - self::SPAN_BOOL_PARAM => array(),//Span 的布尔型参数 - self::SPAN_INT_PARAM => array(),//Span 的整型参数 - self::SPAN_LOG => array(),//Span 的日志 + self::SPAN_TYPE_VALUE => 0, + self::SPAN_LAYER_VALUE => 0, + self::FATHER_SPAN_ID => -1, + self::STARTTIME => '', + self::ENDTIME => '', + //self::COMPONENT_ID => '', + self::COMPONENT_NAME => '', + //self::OPERATION_NAME_ID => '', + //self::PEER_ID => '', + self::PEER => '', + self::IS_ERROR => false, + + self::TAGS => array(),//Span 的整型参数 + self::LOGS => array(),//Span 的日志 ); /** @@ -205,27 +247,33 @@ class SkyWalking if (empty(self::$_appCode)) { throw new Exception("Error : Must set appCode"); } - + if(!$this->appInitRegister()){ + return ; + } //注册一个结束函数 register_shutdown_function(array($this, "__finishAll")); - + //对节点数据进行结构初始化 - $this->_allNodeData = self::$_allPartsNodesStruct; - + $this->_allNodeData = self::$_allNodesStruct; + //对段节点进行初始化 + $this->_allSegment = self::$_allSegmentStruct; + /* * 接收头信息 并对 _swHeaderInfo 进行赋值 * _swHeaderInfo 保存父节点 */ $this->receiveSWHeaderFromCaller(); - - $this->_allNodeData[self::TRACEID] = $this->_generateTraceId(); - - //设置最开始的时间 - $this->_allNodeData[self::STARTTIME] = $this->getMillisecond(); - $this->_allNodeData[self::FATHER_NODE_DATA] = $this->getFatherNodeData(); - $this->_allNodeData[self::APP_CODE] = self::$_appCode; - $this->_allNodeData[self::DISTRIBUTED_TRACEIDS][] = $this->_generateDistributedTraceIds(); - + + //总结阶段的链路全局id + $this->_allNodeData[self::DISTRIBUTED_TRACEIDS] = array($this->_generateTraceId(self::IS_ARRAY)); + + //设置节点id + $this->_allSegment[self::TRACE_SEGMENT_ID] = $this->_generateTraceId(self::IS_ARRAY); + $this->_allSegment[self::APPLICATION_ID] = $this->_getAppId(); + $this->_allSegment[self::APPLICATION_INSTANCE_ID] = $this->_getAppInstanceId(); + $this->_allSegment[self::FATHER_NODE_DATA] = $this->getFatherNodeData(); + + /** * 第一个span节点初始操作 * 当前页 @@ -233,35 +281,27 @@ class SkyWalking $pageUrlAndPeer = $this->getPageUrlAndPeer(); $this->_spanFirstNodeData = self::$_spanNodeDataStruct; $this->_spanFirstNodeData[self::SPAN_ID] = $this->_generateSpanId(); + $this->_spanFirstNodeData[self::SPAN_TYPE_VALUE] = 0; + $this->_spanFirstNodeData[self::SPAN_LAYER_VALUE] = 3; $this->_spanFirstNodeData[self::STARTTIME] = $this->getMillisecond(); - $this->_spanFirstNodeData[self::SPAN_STRING_PARAM]['span.layer'] = 'http'; - $this->_spanFirstNodeData[self::SPAN_STRING_PARAM]['component'] = 'php-server'; - //获取客户端来源ip - $this->_spanFirstNodeData[self::SPAN_STRING_PARAM]['peer.host'] = $this->getIp(); - //$this->_spanFirstNodeData[self::SPAN_STRING_PARAM]['peer.host'] = $pageUrlAndPeer[1]; - $this->_spanFirstNodeData[self::SPAN_SERVER_URI] = $pageUrlAndPeer[0]; - $this->_spanFirstNodeData[self::SPAN_STRING_PARAM]['url'] = $pageUrlAndPeer[0]; - $this->_spanFirstNodeData[self::SPAN_STRING_PARAM]['span.kind'] = 'server'; - } - - - /** - * 开始span信息的生产开始流程 - * TODO 待扩展 - */ - public function startSpan() - { + //$this->_spanFirstNodeData[self::COMPONENT_ID] = 'php-server'; + $this->_spanFirstNodeData[self::COMPONENT_NAME] = 'php-server'; + //$this->_spanFirstNodeData[self::PEER_ID] = 'server'; + $this->_spanFirstNodeData[self::PEER] = '127.0.0.1'; + + // $this->_spanFirstNodeData[self::OPERATION_NAME_ID] = $pageUrlAndPeer[0]; + $parseUrl = parse_url($pageUrlAndPeer[0]); + $host = $parseUrl['host']; + if( !empty( $parseUrl['port'] ) ){ + $host .= ':' . $parseUrl['port']; + } + $this->_spanFirstNodeData[self::OPERATION_NAME] = $host . $parseUrl['path']; + $this->_spanFirstNodeData[self::IS_ERROR] = false; + $this->_spanFirstNodeData[self::TAGS][] = array('k'=>'url','v'=>$pageUrlAndPeer[0]); + } - /** - * 结束span信息 生产流程 - * TODO 待扩展 - */ - public function endSpan() - { - } - /** * 开始span的curl信息的生产开始流程 * 请求curl前的span的生产 @@ -272,45 +312,25 @@ class SkyWalking */ public function startSpanOfCurl($peerHost, &$headers) { + //初始化sanp节点信息 $this->_spanNodeData = self::$_spanNodeDataStruct; $this->_spanNodeData[self::SPAN_ID] = $this->_generateSpanId(); + $this->_spanNodeData[self::SPAN_TYPE_VALUE] = 1; + //使用第一span节点id当场父节点id $this->_spanNodeData[self::FATHER_SPAN_ID] = $this->_spanFirstNodeData[self::SPAN_ID]; $this->_spanNodeData[self::STARTTIME] = $this->getMillisecond(); - - $this->_spanNodeData[self::SPAN_STRING_PARAM]['span.layer'] = 'http'; - $this->_spanNodeData[self::SPAN_STRING_PARAM]['component'] = 'php-curl'; - - //记录当前机器地址 - //$this->_spanNodeData[self::SPAN_STRING_PARAM]['peer.host'] = $_SERVER["SERVER_NAME"]; - //默认80有的情况使用有的值 - $peerPort = 80; - //判断peerHost 还是url - if(filter_var($peerHost, FILTER_VALIDATE_URL) === false){ - //peerHost 处理 - $peerHostArray = explode(":", $peerHost); - $peerHostV = $peerHostArray[0]; - if(!empty($peerHostArray[1])){ - $peerPort = (int)$peerHostArray[1]; - } - }else{ - //url 处理 - $peerUrlArray = parse_url($peerHost); - $peerHostV = $peerUrlArray['host']; - if(!empty($peerUrlArray['port'])){ - $peerPort = (int)$peerUrlArray['port']; - } - } - - $this->_spanNodeData[self::SPAN_STRING_PARAM]['peer.host'] = $peerHostV; - $this->_spanNodeData[self::SPAN_INT_PARAM]['peer.port'] = $peerPort; - - //span.kind - string client 或 server, 指定这个span代表一个客户端还是服务端, curl属于调用别人接口 永远都是客户端 - $this->_spanNodeData[self::SPAN_STRING_PARAM]['span.kind'] = 'client'; + //$this->_spanNodeData[self::COMPONENT_ID] = 'php-curl'; + $this->_spanNodeData[self::COMPONENT_NAME] = 'php-curl'; + + $this->_spanNodeData[self::SPAN_LAYER_VALUE] = 3; + + //$this->_spanNodeData[self::PEER_ID] = 'client'; + $_SWTraceHeader = $this->_buildSWHeaderValue($peerHost); - array_push($headers, "SWTraceContext: " . $_SWTraceHeader['SWTraceContext']); + array_push($headers, "sw3: " . $_SWTraceHeader['SWTraceContext']); } @@ -321,7 +341,7 @@ class SkyWalking public function endSpanOfCurl($curl) { //此次是否采样 - if (!$this->isSampling()) { + if (!$this->isSampling() || $this->_isClose) { return; } @@ -332,20 +352,24 @@ class SkyWalking throw new Exception("Need setting curl Object"); } $curlInfo = curl_getinfo($curl); + $this->_spanNodeData[self::ENDTIME] = $this->getMillisecond(); - $this->_spanNodeData[self::SPAN_SERVER_URI] = $curlInfo['url']; - $this->_spanNodeData[self::SPAN_INT_PARAM]['status_code'] = $curlInfo['http_code']; + //$this->_spanNodeData[self::OPERATION_NAME_ID] = $curlInfo['url']; + $parseUrl = parse_url($curlInfo['url']); + $host = $parseUrl['host']; + if( !empty( $parseUrl['port'] ) ){ + $host .= ':' . $parseUrl['port']; + } + $this->_spanNodeData[self::OPERATION_NAME] = $host . $parseUrl['path']; + $this->_spanNodeData[self::PEER] = $host; + //获取当前服务端口号 - //$this->_spanNodeData[self::SPAN_INT_PARAM]['peer.port'] = (int)$_SERVER["SERVER_PORT"]; if ($curlInfo['http_code'] != 200) { - $this->_spanNodeData[self::SPAN_BOOL_PARAM]['error'] = "true"; - } - if (empty($this->_spanNodeData[self::SPAN_BOOL_PARAM])) { - $this->_spanNodeData[self::SPAN_BOOL_PARAM] = new stdClass(); + $this->_spanNodeData[self::IS_ERROR] = true; } - $this->_spanNodeData[self::SPAN_STRING_PARAM]['url'] = $curlInfo['url']; - + $this->_spanNodeData[self::TAGS][] = array('k'=>'url','v'=>$curlInfo['url']); + $this->setSpanNodeSData($this->_spanNodeData); } @@ -357,29 +381,100 @@ class SkyWalking public function __finishAll() { //此次是否采样 - if (!$this->isSampling()) { + if (!$this->isSampling() || $this->_isClose) { return; } //删除rs if (empty($this->_allNodeData[self::FATHER_NODE_DATA])) { unset($this->_allNodeData[self::FATHER_NODE_DATA]); } + /** * 首节点插入到span节点集中 */ $this->_spanFirstNodeData[self::ENDTIME] = $this->getMillisecond(); - $this->_spanFirstNodeData[self::SPAN_BOOL_PARAM] = new stdClass(); - $this->_spanFirstNodeData[self::SPAN_INT_PARAM]['status_code'] = 200; - $this->_spanFirstNodeData[self::SPAN_INT_PARAM]['peer.port'] = 80; + array_unshift($this->_spansNodeData, $this->_spanFirstNodeData); - - $this->_allNodeData[self::ENDTIME] = $this->getMillisecond(); - $this->_allNodeData[self::SPANS_NODE_DATA] = $this->_spansNodeData; - $results = json_encode($this->_allNodeData); + $this->_allSegment[self::SPANS_NODE_DATA] = $this->_spansNodeData; + + // $this->_allNodeData[self::ENDTIME] = $this->getMillisecond(); + $this->_allNodeData[self::SEGMENT] = $this->_allSegment; + $results = json_encode(array($this->_allNodeData)); //默认使用写日志的方式 $this->writeLog($results); + return $results; } + + /** + * 设置父节点数据 + * 数据格式 + * "rs": [父节点 + * ["ts": "parent_trace_0"], --父节点,传给本子节点的TraceId + * ["si": 1], --父节点,传给本子节点的SpanId + * ["ac": "REMOTE_APP"], --父节点,传给本子节点的App Code + * ["ph": "10.2.3.16:8080"] --父节点,传给本子节点的PeerHost + * ] + * @return array + */ + public function getFatherNodeData() + { + if (empty($this->_swHeaderInfo)) { + return array(); + } + //对父节点进行初始化 + $this->_fatherNodeData = self::$_fatherNodesStruct; + + $this->_fatherNodeData[self::PARENT_TRACE_SEGMENT_ID] = explode('.', $this->_swHeaderInfo['TraceId']); + $this->_fatherNodeData[self::PARENT_APPLICATION_ID] = $this->_swHeaderInfo['ParentAppInstanceid']; + $this->_fatherNodeData[self::PARENT_SPAN_ID] = $this->_swHeaderInfo['SpanId']; + $this->_fatherNodeData[self::PARENT_SERVICE_ID] = $this->_swHeaderInfo['ParentAppname']; + $this->_fatherNodeData[self::PARENT_SERVICE_NAME] = $this->_swHeaderInfo['ParentAppname']; + $this->_fatherNodeData[self::NETWORK_ADDRESS_ID] = $this->_swHeaderInfo['PeerHost']; + $this->_fatherNodeData[self::NETWORK_ADDRESS] = $this->_swHeaderInfo['PeerHost']; + $this->_fatherNodeData[self::ENTRY_APPLICATION_INSTANCE_ID] = $this->_swHeaderInfo['EntryAppInstanceid']; + $this->_fatherNodeData[self::ENTRY_SERVICE_ID] = $this->_swHeaderInfo['EntryAppname']; + $this->_fatherNodeData[self::ENTRY_SERVICE_NAME] = $this->_swHeaderInfo['EntryAppname']; + $this->_fatherNodeData[self::REF_TYPE_VALUE] = 0; + + + return $this->_fatherNodeData; + } + + /** + * 设置span节点数据 + * @param $nodeData + * 数据格式 + * [ + * ["si": 1], --Span A的SpanId + * ["ps": -1], --父节点传过来的SpanId + * ["st": 1490097253228], --Span A的开始时间,创建Span A时设置 + * ["et": 1494965637898], --Span A的结束时间,Span A处理完时设置 + * ["on": "/serviceA"], --Span A的服务URI + * ["ts": --Span A的字符串型参数 + * ["span.layer": "http"] --Span A的协议,分为http、rpc、db + * ["component": "Tomcat" ] --Span A的节点组件,如Tomcat、Nginx、HttpClient、DbClient + * ["peer.host": "127.0.0.1"] --Span A的请求源IP + * ["span.kind": "server"] --Span A的节点组件类型,分为server、client + * ["url": "10.2.3.16:8080/serviceA"] --Span A的访问地址URL + * ], + * ["tb": []], --Span A的布尔值型参数 + * ["ti": [ --Span A的整数值型参数 + * "peer.port": 80 --Span A的请求源Port + * ]], + * ["lo": []] --Span A的日志 + * ] + * @return $this + */ + public function setSpanNodeSData($nodeData) + { + array_push($this->_spansNodeData, $nodeData); + return $this; + } + + public function close(){ + $this->_isClose = 1; + } /** * 设置 要写日志的路径 @@ -391,7 +486,45 @@ class SkyWalking $this->_logPath = $logPath; return $this; } - + /** + * 获取写日志路径 + * + * @since 2017年11月28日 + * @copyright + * @return return_type + */ + public function getLogPath(){ + if (!empty($this->_logPath)) { + $logPath = rtrim($this->_logPath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; + } else { + $logPath = DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR; + } + return $logPath; + } + /** + * 设置注册apm地址 + * @param $registerUrl + * @since 2017年11月28日 + * @copyright + * @return return_type + */ + public function setRegisterUrl($registerUrl){ + $this->_registerUrl = $registerUrl; + return $this; + } + /** + * 获取注册apm地址 + * @return string + * @since 2017年11月28日 + * @copyright + * @return string + */ + public function getRegisterUrl(){ + if(!empty($this->_registerUrl)) return $this->_registerUrl; + + return self::DEFAULT_REGISTER_URL; + } + /** * 设置采样率 最大值 100 * @param int $percent @@ -399,12 +532,16 @@ class SkyWalking */ public function setSamplingRate($percent) { - if (!empty($percent) && ctype_digit("$percent")) { - if ($percent >= 100) { - $percent = 100; - } - $this->_samplingRate = $percent; + if ($percent >= 100) { + $percent = 100; } + $this->_samplingRate = $percent; + + return $this; + } + + public function closeSampling(){ + $this->_isSampling = false; return $this; } @@ -417,30 +554,16 @@ class SkyWalking private function isSampling() { //判断没有计算过采样率 - if (is_bool($this->_isSampling) !== true) { - - //继承接受的采样率 - if (!empty($this->_swHeaderText)) { - $this->_isSampling = true; - if ($this->_swHeaderInfo['IsSample'] != 1) { - $this->_isSampling = false; - } - } /** - * 没有继承接收到的采样率 - */ - else { - //若若没有设置采样率,则默认为100%采样 - $this->_isSampling = true; - if ($this->_samplingRate === null) { - //throw new Exception("Please set sampling rate"); - $this->_samplingRate = 100; - } - - //根据设置的值计算采样率 - if ($this->_samplingRate < 100) { - $r = rand(1, 100); - $this->_isSampling = $r <= $this->_samplingRate; - } + if (!isset($this->_isSampling)) { + + $this->_isSampling = true; + if ($this->_samplingRate === null) { + $this->_samplingRate = 100; + } + //根据设置的值计算采样率 + if ($this->_samplingRate < 100) { + $r = rand(1, 100); + $this->_isSampling = ($r <= $this->_samplingRate); } } return $this->_isSampling; @@ -456,28 +579,114 @@ class SkyWalking if (!empty($this->_logPath)) { $logPath = rtrim($this->_logPath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; } else { -// throw new Exception("Please set log path: setLogPath()"); $logPath = DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR; } - $logFilename = strtolower($logPath . 'skywalking.' . date("Ymd") . '.log'); + $logFilename = $logPath . 'skywalking.' . date("Ymd") . '.log'; error_log($text . "\n", 3, $logFilename); } - - + + /** + * 获取 id parts + * + * @since 2017年11月23日 + * @copyright + * @return return_type + */ + private function _getIdParts(){ + + $serverIp = $this->_getCurrentMachineIp(); + $intUuid = base_convert(uniqid(), 16, 10); + return array( + (int)ip2long($serverIp), + (int)getmypid(), + $intUuid, + ); + } + /** * 生成TraceID,用于此次请求的ID + * @param boolean $isArray + * @return mixed|string + * @since 2017年11月27日 + * @copyright + * @return mixed|string */ - private function _generateTraceId() + private function _generateTraceId($isArray = false) { - //沿用父节点的TraceId ; 本节点生成的全链路系统唯一的事务编号,推荐生成规则为:Segment.毫秒时间戳.UUID后7位的哈希码.当前进程号PID.当前线程ID.当前线程生成的流水号.ip + //沿用父节点的TraceId ; 本节点生成的全链路系统唯一的事务编号。 if (!empty($this->_swHeaderInfo)) { - return $this->_swHeaderInfo['TraceId']; + $this->_traceId = $this->_swHeaderInfo['TraceId']; } if (empty($this->_traceId)) { - $this->_traceId = "Segment." . $this->makeTraceId(); + $this->_traceId = $this->makeTraceId(); + } + + if($isArray){ + $traceIdArray = explode('.', $this->_traceId); + foreach ( $traceIdArray as $key => $val ){ + $traceIdArray[$key] = (int)$val; + } + return $traceIdArray; } return $this->_traceId; } + /** + * 获取父节点注册id + * + * @since 2017年11月28日 + * @copyright + * @return return_type + */ + private function _parentAppInstanceid(){ + + //沿用父节点的ParentAppInstanceid ; 本节点生成的全链路系统唯一的事务编号。 + return $this->_getAppInstanceId(); + } + /** + * 获取入口节点数据 + * + * @since 2017年11月28日 + * @copyright + * @return return_type + */ + private function _entryAppnameOperationId(){ + if(!empty( $this->_swHeaderInfo['EntryAppnameOperationId'] )){ + return $this->_swHeaderInfo['EntryAppnameOperationId']; + } + return $this->_spanFirstNodeData[self::SPAN_ID]; + } + private function _parentAppnameOperationId(){ + return $this->_spanFirstNodeData[self::SPAN_ID]; + } + /** + * 获取入口节点数据 + * + * @since 2017年11月28日 + * @copyright + * @return return_type + */ + private function _entryAppName(){ + if(!empty( $this->_swHeaderInfo['EntryAppname'] )){ + return $this->_swHeaderInfo['EntryAppname']; + } + return self::$_appCode; + } + private function _parentAppName(){ + return self::$_appCode; + } + /** + * 获取入口节点注册id + * + * @since 2017年11月28日 + * @copyright + * @return return_type + */ + private function _entryAppInstanceid(){ + if(!empty( $this->_swHeaderInfo['EntryAppInstanceid'] )){ + return $this->_swHeaderInfo['EntryAppInstanceid']; + } + return $this->_getAppInstanceId(); + } /** @@ -490,16 +699,20 @@ class SkyWalking return $this->_swHeaderInfo['DistributedTraceIds']; } if (empty($this->_distributedTraceIds)) { - $this->_distributedTraceIds = "Trace." . $this->makeTraceId(); + $this->_distributedTraceIds = $this->makeTraceId(); } return $this->_distributedTraceIds; } - - private function makeTraceId() - { - //生产唯一码毫秒时间戳.uuid.当前进程号PID.当前线程ID.当前线程生成的流水号.ip - $millisecond = $this->getMillisecond(); - $uuid = uniqid(); + + /** + * 当前机器ip + * + * @since 2017年11月23日 + * @copyright + * @return return_type + */ + private function _getCurrentMachineIp(){ + if (defined('PHP_SAPI') && PHP_SAPI == 'cli') { $ip = '127.0.0.1'; } elseif (isset($_SERVER)) { @@ -511,8 +724,16 @@ class SkyWalking } else { $ip = getenv('SERVER_ADDR'); } - - return sprintf("%s.%s.%s.0.0.%s", $millisecond, $uuid, getmypid(), $ip); + return $ip; + } + + private function makeTraceId() + { + //生产唯一码毫秒时间戳.uuid.当前进程号PID.当前线程ID.当前线程生成的流水号.ip + + $makeTraceIdArray = $this->_getIdParts(); + + return implode('.', $makeTraceIdArray); } private function getIp() @@ -548,7 +769,7 @@ class SkyWalking $pageURL .= $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]; return array($pageURL, $peer); } - + /** * 生成 SpanId * 用于此次调用的区块标示 @@ -565,73 +786,6 @@ class SkyWalking return $millisecond; } - /** - * 设置appCode,用于标示应用本身的名称 - * @param string $appCode - */ - public function setAppCode($appCode) - { - - } - - - /** - * 设置父节点数据 - * 数据格式 - * "rs": [父节点 - * ["ts": "parent_trace_0"], --父节点,传给本子节点的TraceId - * ["si": 1], --父节点,传给本子节点的SpanId - * ["ac": "REMOTE_APP"], --父节点,传给本子节点的App Code - * ["ph": "10.2.3.16:8080"] --父节点,传给本子节点的PeerHost - * ] - * @return array - */ - public function getFatherNodeData() - { - if (empty($this->_swHeaderInfo)) { - return array(); - } - //对父节点进行初始化 - $this->_fatherNodeData = self::$_fatherNodesStruct; - $this->_fatherNodeData[self::TRACEID] = $this->_swHeaderInfo['TraceId']; - $this->_fatherNodeData[self::SPAN_ID] = (int)$this->_swHeaderInfo['SpanId']; - $this->_fatherNodeData[self::APP_CODE] = $this->_swHeaderInfo['AppCode']; - $this->_fatherNodeData[self::PEERHOST] = $this->_swHeaderInfo['PeerHost']; - - return $this->_fatherNodeData; - } - - /** - * 设置span节点数据 - * @param $nodeData - * 数据格式 - * [ - * ["si": 1], --Span A的SpanId - * ["ps": -1], --父节点传过来的SpanId - * ["st": 1490097253228], --Span A的开始时间,创建Span A时设置 - * ["et": 1494965637898], --Span A的结束时间,Span A处理完时设置 - * ["on": "/serviceA"], --Span A的服务URI - * ["ts": --Span A的字符串型参数 - * ["span.layer": "http"] --Span A的协议,分为http、rpc、db - * ["component": "Tomcat" ] --Span A的节点组件,如Tomcat、Nginx、HttpClient、DbClient - * ["peer.host": "127.0.0.1"] --Span A的请求源IP - * ["span.kind": "server"] --Span A的节点组件类型,分为server、client - * ["url": "10.2.3.16:8080/serviceA"] --Span A的访问地址URL - * ], - * ["tb": []], --Span A的布尔值型参数 - * ["ti": [ --Span A的整数值型参数 - * "peer.port": 80 --Span A的请求源Port - * ]], - * ["lo": []] --Span A的日志 - * ] - * @return $this - */ - private function setSpanNodeSData($nodeData) - { - array_push($this->_spansNodeData, $nodeData); - return $this; - } - /** * 获取接收到 SWTraceContext 的 header */ @@ -640,12 +794,14 @@ class SkyWalking if (!empty($_SERVER['HTTP_SWTRACECONTEXT'])) { $this->_swHeaderText = $_SERVER['HTTP_SWTRACECONTEXT']; list( - $this->_swHeaderInfo['TraceId'], + $this->_swHeaderInfo['traceId'], $this->_swHeaderInfo['SpanId'], - $this->_swHeaderInfo['AppCode'], + $this->_swHeaderInfo['ParentAppInstanceid'], + $this->_swHeaderInfo['EntryAppInstanceid'], $this->_swHeaderInfo['PeerHost'], - $this->_swHeaderInfo['DistributedTraceIds'], - $this->_swHeaderInfo['IsSample'], + $this->_swHeaderInfo['EntryAppnameOperationId'], + $this->_swHeaderInfo['ParentAppnameOperationId'], + $this->_swHeaderInfo['DistributedTraceIds'] ) = explode('|', $this->_swHeaderText); } return $this->_swHeaderInfo; @@ -663,11 +819,201 @@ class SkyWalking $_SWHeader['traceId'] = $this->_generateTraceId(); $_SWHeader['SpanId'] = $this->_generateSpanId(); - $_SWHeader['AppCode'] = self::$_appCode; - $_SWHeader['PeerHost'] = $peerHost; + $_SWHeader['ParentAppInstanceid'] = $this->_parentAppInstanceid(); + $_SWHeader['EntryAppInstanceid'] = $this->_entryAppInstanceid(); + $_SWHeader['PeerHost'] = '#' . $peerHost; + $_SWHeader['EntryAppnameOperationId'] = $this->_entryAppnameOperationId(); + $_SWHeader['ParentAppnameOperationId'] = $this->_parentAppnameOperationId(); $_SWHeader['DistributedTraceIds'] = $this->_generateDistributedTraceIds(); - $_SWHeader['IsSample'] = (int)$this->isSampling(); return array('SWTraceContext' => implode('|', $_SWHeader)); } + + /** + * 设置应用注册 + * + * @since 2017年11月23日 + * @copyright + * @return return_type + */ + private function appInitRegister(){ + + if($this->_isClose){ + return false; + } + $appId = $this->AppId(); + if(empty($appId)){ + return false; + } + $appInstanceId = $this->AppInstanceId($appId); + if($appInstanceId !== 0 && empty($appInstanceId)){ + return false; + } + $this->_appIds = array($appId, $appInstanceId); + + + return true; + } + + /** + * 获取 app_id + * @return mixed + * @since 2017年11月27日 + * @copyright + * @return mixed + */ + private function _getAppId(){ + return $this->_appIds[0]; + } + + /** + * 获取 app_id + * @return mixed + * @since 2017年11月27日 + * @copyright + * @return mixed + */ + private function _getAppInstanceId(){ + return $this->_appIds[1]; + } + + + /** + * 获取appid + * + * @since 2017年11月23日 + * @copyright + * @return return_type + */ + private function AppId(){ + + $processNo = getmypid(); + $fileName = $this->getLogPath() . $processNo . '.appid.pid'; + $appId = $this->getfilesText($fileName); + if(empty($appId)){ + + $param ='["'. self::$_appCode .'"]'; + $appIds = $this->doRequest($param, $this->getRegisterUrl() . '/application/register'); + $appIds = json_decode($appIds, true); + $appId = $appIds[0]['i']; + if(!empty($appId)){ + $this->fwriteFilesText($fileName, $appId); + } + } + if(empty($appId)){ + return false; + } + + return (int)$appId; + } + + /** + * 获取appid的实例id + * @param unknown $applicationId + * @since 2017年11月23日 + * @copyright + * @return return_type + */ + private function AppInstanceId($appId){ + + $processNo = getmypid(); + $fileName = $this->getLogPath() . $processNo . '.instance.appid.pid'; + $appInstanceId = $this->getfilesText($fileName); + if($appInstanceId !== '0' && empty($appInstanceId)){ + + + $rt = date('YmdHis'); + $ip = $this->_getCurrentMachineIp(); + $agentUuid = self::$_appCode . '.' . $ip; + $hostname = ''; + if(!empty( $_SERVER['HOSTNAME']) ){ + $hostname = $_SERVER['HOSTNAME']; + } + + $param = array( + 'ai' => (int)$appId, + 'au' => $agentUuid, + 'rt' => $rt, + 'oi' => array( + 'osName' => PHP_OS, + 'hostname' => $hostname, + 'processNo' => $processNo, + 'ipv4s' => array($ip), + ), + ); + $appInstanceIds = $this->doRequest(json_encode($param), $this->getRegisterUrl() . '/instance/register'); + $appInstanceIds = json_decode($appInstanceIds, true); + if(isset($appInstanceIds['ii'])){ + $appInstanceId = (string)$appInstanceIds['ii']; + } + if(!empty($appInstanceId) || $appInstanceId === '0'){ + $this->fwriteFilesText($fileName, $appInstanceId); + } + } + if($appInstanceId !== '0' && empty($appInstanceId)){ + return false; + } + + return (int)$appInstanceId; + + } + + /** + * http请求 + * @param unknown $params + * @since 2017年11月28日 + * @copyright + * @return return_type + */ + private function doRequest($params, $registerUrl) { + + if($this->_isClose || !$this->isSampling()){ + return ; + } + //不支持curl 关闭改功能 + if( !function_exists('curl_init') ){ + $this->_isClose = false; + } + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $registerUrl); + curl_setopt($ch, CURLOPT_AUTOREFERER, true); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_TIMEOUT,1); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $params); + $result = curl_exec($ch);//运行curl + $info = curl_getinfo($ch); + curl_close($ch); + + if( 0 == strlen($result) || ($info['http_code'] != 200) ){ + return false; + } + return $result; + } + + /** + * 获取文件当前行内容 + * @param unknown $filename + * @since 2017年11月28日 + * @copyright + * @return return_type + */ + private function getfilesText($filename){ + try { + $file = new SplFileObject($filename); + return $file->current(); + + } catch (\RuntimeException $e) { + return null; + } + } + + private function fwriteFilesText($filename, $text){ + try { + $file = new SplFileObject($filename, "w"); + $file->fwrite($text); + } catch (\RuntimeException $e) { + } + + } } diff --git a/sky-php7ext/README.md b/sky-php7ext/README.md index ce431e6f5da53078e207c7b953c44db3cdde155e..b417f4eb6d16573b6dee1e28587cd72b34c58119 100644 --- a/sky-php7ext/README.md +++ b/sky-php7ext/README.md @@ -24,31 +24,9 @@ copy ini to php.ini the current phpext works with PHP 7.0-7.9.99 。 this extension references something external, use with: pphcurl、phpjson and phpstandard - +need to install, Please refer to: https://github.com/grpc/grpc/blob/master/INSTALL.md ### Documentation - https://github.com/OpenSkywalking/skywalking/wiki ### Quick Start and Examples -set php.ini skywalking.auto_open = On (Automatic writing **Ignore the following**) -OR skywalking.auto_open = OFF (the project int code )As below: - - // must put these code at the beginning !!! - - .... - .... - - - $ch = curl_init(); - curl_setopt($ch); - - SkyWalking::getInstance()->startSpanOfCurl("www.api.com", $headers); - .... - .... - - curl_setopt($ch); - $rs = curl_exec($ch); - - SkyWalking::getInstance()->endSpanOfcurl($ch); - - .... - .... +set php.ini skywalking.auto_open = On (Automatic writing **Ignore the following**) \ No newline at end of file diff --git a/sky-php7ext/README_ZH.md b/sky-php7ext/README_ZH.md new file mode 100644 index 0000000000000000000000000000000000000000..26c88e24eec084a7d3281a808214da7e9bcbd0d0 --- /dev/null +++ b/sky-php7ext/README_ZH.md @@ -0,0 +1,30 @@ +# PHP SkyWalking Class: SkyWalking PHP client + + +--- + +- [安装](#installation) +- [要求](#requirements) +- [Quick Start and Examples](#quick-start-and-examples) + +--- + +### Installation +快速安装 + +复制ini内容到php.ini + + git clone https://github.com/SkywalkingContrib/skywalking-php-sdk.git + cd skywalking-php-sdk/sky-php7ext + phpize + ./configure + make -j [number_of_processor_cores] # eg. make -j 4 + make install +### Requirements + +扩展支持版本 7.0-7.9.99 。 +这个扩展需要其他扩展支持: pphcurl、phpjson和phpstandard 包 +需要安装GRPC 请参照 : https://github.com/grpc/grpc/blob/master/INSTALL.md + +### 快速启动 +设置 php.ini skywalking.auto_open = On (自动开启信息抓取 **Ignore the following**) diff --git a/sky-php7ext/config.m4 b/sky-php7ext/config.m4 index 92ad5c08f2827e44e4f1ed2a586cb3c59fbd7d47..b1aa6add2ba66a75aaefc5850dd261845acf79b6 100644 --- a/sky-php7ext/config.m4 +++ b/sky-php7ext/config.m4 @@ -62,6 +62,43 @@ if test "$PHP_SKYWALKING" != "no"; then dnl ]) dnl dnl PHP_SUBST(SKYWALKING_SHARED_LIBADD) + PHP_REQUIRE_CXX() - PHP_NEW_EXTENSION(skywalking, skywalking.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) + KYWALKING_LIBS=" -L/usr/local/lib " + KYWALKING_LIBS+=`pkg-config --libs protobuf grpc++ grpc` + KYWALKING_LIBS+="-Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed -ldl" + + AC_OUTPUT_COMMANDS( + protoc -I ./protos --cpp_out=./grpc ./protos/DiscoveryService.proto + protoc -I ./protos --cpp_out=./grpc ./protos/ApplicationRegisterService.proto + protoc -I ./protos --cpp_out=./grpc ./protos/TraceSegmentService.proto + ) + AC_OUTPUT_COMMANDS( + protoc -I ./protos --grpc_out=./grpc --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` ./protos/DiscoveryService.proto + protoc -I ./protos --grpc_out=./grpc --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` ./protos/ApplicationRegisterService.proto + protoc -I ./protos --grpc_out=./grpc --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` ./protos/TraceSegmentService.proto + ) + AC_OUTPUT_COMMANDS( + mv grpc/DiscoveryService.grpc.pb.cc grpc/DiscoveryService-grpc.pb.cc + mv grpc/ApplicationRegisterService.grpc.pb.cc grpc/ApplicationRegisterService-grpc.pb.cc + mv grpc/TraceSegmentService.grpc.pb.cc grpc/TraceSegmentService-grpc.pb.cc + ) + + PHP_EVAL_LIBLINE($KYWALKING_LIBS, SKYWALKING_SHARED_LIBADD) + + + PHP_NEW_EXTENSION(skywalking, \ + skywalking.c \ + grpc/greeter_client.cc \ + grpc/DiscoveryService.pb.cc \ + grpc/DiscoveryService-grpc.pb.cc \ + grpc/ApplicationRegisterService.pb.cc \ + grpc/ApplicationRegisterService-grpc.pb.cc \ + grpc/TraceSegmentService.pb.cc \ + grpc/TraceSegmentService-grpc.pb.cc \ + , $ext_shared,, -std=c++11 -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) + + PHP_ADD_BUILD_DIR($ext_builddir/grpc) + + PHP_SUBST(SKYWALKING_SHARED_LIBADD) fi diff --git a/sky-php7ext/grpc/common_struct.h b/sky-php7ext/grpc/common_struct.h new file mode 100644 index 0000000000000000000000000000000000000000..5b567fbe749fda2965208ead99a54d86e55964b0 --- /dev/null +++ b/sky-php7ext/grpc/common_struct.h @@ -0,0 +1,157 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: DiscoveryService.proto + +#ifndef DISCOVERY_CLIENT_C_H +#define DISCOVERY_CLIENT_C_H + + +#define METHOD__GO_REGISTER 1 + +#define METHOD__GO_REGISTER_INSTANCE 2 + +#define METHOD__SEND_TRACE_SEGMENT 3 + + +typedef struct _RegisterParamtruct +{ + char* appCode; +}RegisterParamtruct; + +typedef struct _RegisterInstanceParamtruct +{ + char* agentUUID; + char* osName;; + char* hostname; + char* ipv4s; + int applicationId; + long registerTime; + int processNo; +}RegisterInstanceParamtruct; + +typedef enum _SpanTypeStruct +{ + Entry_x, + Exit_x, + Local_x +}SpanTypeStruct; + +typedef enum _SpanLayerStruct +{ + Unknown_x, + Database_x, + RPCFramework_x, + Http_x, + MQ_x, + Cache_x +}SpanLayerStruct; + +typedef struct _KeyWithStringValueStruct +{ + int key; + char *value; +}KeyWithStringValueStruct; + +typedef struct _LogMessageStruct +{ + long time; + KeyWithStringValueStruct* data; +}LogMessageStruct; + +typedef enum _RefTypeStruct +{ + CrossProcess_x, + CrossThread_x +}RefTypeStruct; + +typedef struct _UniqueIdStruct +{ + long idParts; +}UniqueIdStruct; + +typedef struct _TraceSegmentReferenceStruct +{ + RefTypeStruct* refType; + UniqueIdStruct* parentTraceSegmentId; + int parentSpanId; + int parentApplicationInstanceId; + int networkAddress; + int networkAddressId; + int entryApplicationInstanceId; + char* entryServiceName; + int entryServiceId; + char* parentServiceName; + int* parentServiceId; +}TraceSegmentReferenceStruct; + +typedef struct _SpanObjectStruct +{ + int spanId; + int parentSpanId; + long startTime; + long endTime; + TraceSegmentReferenceStruct* refs; + int operationNameId; + char *operationName; + int peerId; + char *peer; + SpanTypeStruct* spanType; + SpanLayerStruct* spanLayer; + int componentId; + int isError; + KeyWithStringValueStruct* tags; + LogMessageStruct* logs; +}SpanObjectStruct; + + + +typedef struct _comListNode +{ + UniqueIdStruct* data; + struct _comListNode* next; +} comListNode; + + +typedef struct _comList +{ + struct _comListNode* head; + struct _comListNode* tail; + int count; +} comList; + + +typedef struct _TraceSegmentObjectStruct +{ + comList* traceSegmentIdList; + SpanObjectStruct *spans; + char *segment; + int applicationId; + int applicationInstanceId; + int isSizeLimited; +}TraceSegmentObjectStruct; + +typedef struct _SendTraceSegmentParamStruct +{ + TraceSegmentObjectStruct* traceSegment; +}SendTraceSegmentParamStruct; + +typedef union _ParamDataStruct +{ + RegisterParamtruct* registerParam; + RegisterInstanceParamtruct* registerInstanceParam; + SendTraceSegmentParamStruct* sendTraceSegmentParam; +} ParamDataStruct; + +typedef struct _UpstreamSegmentStruct +{ + UniqueIdStruct* globalTraceIds; + char *segment; +}UpstreamSegmentStruct; + +typedef struct AppInstanceStruct +{ + int applicationId; + int applicationInstanceId; +} AppInstance; + + +#endif /* #ifndef DISCOVERY_CLIENT_C_H */ \ No newline at end of file diff --git a/sky-php7ext/grpc/greeter_client.cc b/sky-php7ext/grpc/greeter_client.cc new file mode 100644 index 0000000000000000000000000000000000000000..5cbbeec0407549f6ba164209c695b5590b6545de --- /dev/null +++ b/sky-php7ext/grpc/greeter_client.cc @@ -0,0 +1,223 @@ +/* + * + * Copyright 2015 gRPC 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. + * + */ + +#include +#include +#include + +#include + +#include "ApplicationRegisterService.grpc.pb.h" +#include "DiscoveryService.grpc.pb.h" +#include "TraceSegmentService.grpc.pb.h" + +#include "common_struct.h" + +using grpc::Channel; +using grpc::ClientContext; +using grpc::Status; +using grpc::ClientReader; +using grpc::ClientReaderWriter; +using grpc::ClientWriter; + + +extern "C" int goSkyGrpc(char*host, int method, ParamDataStruct* paramData, void (*callfuct)( AppInstance* ) ); + +class GreeterClient { + public: + GreeterClient(std::shared_ptr channel) { + channel_ = channel; + } + + // Assembles the client's payload, sends it and presents the response back + // from the server. + AppInstance* goRegister(const std::string& appCode) { + std::unique_ptr stub_; + stub_ = ApplicationRegisterService::NewStub(channel_) ; + // Data we are sending to the server. + Application request; + request.set_applicationcode( appCode ); + // Container for the data we expect from the server. + ApplicationMapping reply; + // Context for the client. It could be used to convey extra information to + // the server and/or tweak certain RPC behaviors. + ClientContext context; + + + KeyWithIntegerValue kwiv; + // The actual RPC. + Status status = stub_->applicationCodeRegister(&context, request, &reply); + AppInstance* appInstance = (AppInstance*)malloc(sizeof(AppInstance)); + // Act upon its status. + if (status.ok()) { + kwiv = reply.application(); + appInstance->applicationId = kwiv.value(); + return appInstance; + } + return NULL; + } + + // Assembles the client's payload, sends it and presents the response back + // from the server. + AppInstance* goRegisterInstance( + std::string agentUUID, + std::string osName, + std::string hostname, + std::string ipv4s, + int applicationId, + long registerTime, + int processNo + ) { + + std::unique_ptr stub_; + stub_ = InstanceDiscoveryService::NewStub(channel_); + // Data we are sending to the server. + ApplicationInstance request; + request.set_applicationid( applicationId ); + request.set_agentuuid( agentUUID ); + request.set_registertime( registerTime ); + + OSInfo* osinfo = new OSInfo; + request.set_allocated_osinfo( osinfo ); + osinfo->set_osname( osName ); + osinfo->set_hostname( hostname ); + osinfo->set_processno( processNo ); + osinfo->add_ipv4s( ipv4s ); + + AppInstance* appInstancestruct = (AppInstance*)malloc(sizeof(AppInstance)); + + // Container for the data we expect from the server. + ApplicationInstanceMapping reply; + + // Context for the client. It could be used to convey extra information to + // the server and/or tweak certain RPC behaviors. + ClientContext context; + + // The actual RPC. + Status status = stub_->registerInstance(&context, request, &reply); + //free OSInfo + //delete osinfo; + // Act upon its status. + if (status.ok()) { + + appInstancestruct->applicationId = reply.applicationid(); + appInstancestruct->applicationInstanceId = reply.applicationinstanceid(); + return appInstancestruct; + } + return NULL; + + + } + + + void sendTrace( TraceSegmentObjectStruct* traceSegment ) { + + + std::unique_ptr stub_; + + stub_ = TraceSegmentService::NewStub(channel_); + // Data we are sending to the server. + UpstreamSegment request ; + //UniqueId + UniqueId* uniqueId; + + uniqueId = request.add_globaltraceids(); + comListNode* com_list = traceSegment->traceSegmentIdList->head; + while(com_list != NULL) + { + uniqueId->add_idparts(com_list->data->idParts); + com_list = com_list->next; + } + if( traceSegment->segment ){ + request.set_segment(traceSegment->segment); + + Downstream reply; + + ClientContext context; + + grpc_connectivity_state state = channel_->GetState(false); + + if( state == GRPC_CHANNEL_TRANSIENT_FAILURE ){ + return ; + } + + std::unique_ptr > writer( stub_->collect(&context, &reply)); + writer->Write(request); + writer->WritesDone(); + writer->Finish(); + + } + + } + + private: + std::shared_ptr channel_; +}; + + + +int goSkyGrpc(char *host, int method, ParamDataStruct* paramData, void (*callfuct)( AppInstance* ) ) { + + std::shared_ptr channel = grpc::CreateChannel( + host, grpc::InsecureChannelCredentials()); + static GreeterClient greeter(channel); + + switch (method) { + case METHOD__GO_REGISTER: + { + std::string appCode( paramData->registerParam->appCode); + callfuct(greeter.goRegister(appCode)); + } + break; + case METHOD__GO_REGISTER_INSTANCE: + + { + std::string agentUUID(paramData->registerInstanceParam->agentUUID); + std::string osName(paramData->registerInstanceParam->osName); + std::string hostname(paramData->registerInstanceParam->hostname); + std::string ipv4s(paramData->registerInstanceParam->ipv4s); + int applicationId = paramData->registerInstanceParam->applicationId; + long registerTime = paramData->registerInstanceParam->registerTime; + int processNo = paramData->registerInstanceParam->processNo; + callfuct( + greeter.goRegisterInstance( + agentUUID, + osName, + hostname, + ipv4s, + applicationId, + registerTime, + processNo + ) + ); + } + break; + case METHOD__SEND_TRACE_SEGMENT: + { + greeter.sendTrace( paramData->sendTraceSegmentParam->traceSegment ); + } + break; + default: + return 0; + break; + } + + + + return 1; +} diff --git a/sky-php7ext/php.ini b/sky-php7ext/php.ini index 0d9cf75da4359f46ac8df16b340de3159405d06c..a7c9556d1b17b0a7cdf4366943224a9b9a6fba91 100644 --- a/sky-php7ext/php.ini +++ b/sky-php7ext/php.ini @@ -8,8 +8,10 @@ [skywalking] -skywalking.app_code = mapi +skywalking.app_code = api skywalking.sampling_rate = 99.22; skywalking.log_path = /tmp/log skywalking.header_client_ip_name = HTTP_DD_REAL_IP -skywalking.auto_open = On \ No newline at end of file +skywalking.auto_open = On +skywalking.send_type = 1 +skywalking.grpc_trace = 127.0.0.1:50051 \ No newline at end of file diff --git a/sky-php7ext/php_skywalking.h b/sky-php7ext/php_skywalking.h index fd809bcfacc660c9c5e27caab6d7ce6d931a8b09..d26a185d1d2e43a3f017f6171d49032f2db56198 100644 --- a/sky-php7ext/php_skywalking.h +++ b/sky-php7ext/php_skywalking.h @@ -24,7 +24,7 @@ extern zend_module_entry skywalking_module_entry; #define phpext_skywalking_ptr &skywalking_module_entry -#define PHP_SKYWALKING_VERSION "0.1.0" /* Replace with version number for your extension */ +#define PHP_SKYWALKING_VERSION "0.2.0" /* Replace with version number for your extension */ #ifdef PHP_WIN32 # define PHP_SKYWALKING_API __declspec(dllexport) @@ -44,25 +44,58 @@ extern zend_module_entry skywalking_module_entry; #define SKY_G(v) (skywalking_globals.v) #endif -#define SKYWALKING_TRACEID "ts" //TraceId -#define SKYWALKING_STARTTIME "st"//开始时间 -#define SKYWALKING_ENDTIME "et" //结束时间 -#define SKYWALKING_APP_CODE "ac"// App Code -#define SKYWALKING_FATHER_NODE_DATA "rs"//父节点数据 -#define SKYWALKING_SPANS_NODE_DATA "ss"//span节点数据集合 -#define SKYWALKING_DISTRIBUTED_TRACEIDS "gt" //DistributedTraceIds -#define SKYWALKING_SPAN_ID "si"//SpanId -#define SKYWALKING_PEERHOST "ph"//PeerHost -#define SKYWALKING_FATHER_SPAN_ID "ps"//父节点传过来的SpanId -#define SKYWALKING_SPAN_SERVER_URI "on" // Span 的服务URI -#define SKYWALKING_SPAN_STRING_PARAM "ts" //Span 的字符串型参数 -#define SKYWALKING_SPAN_BOOL_PARAM "tb" //Span 的字符串型参数 -#define SKYWALKING_SPAN_INT_PARAM "ti" //Span 的字符串型参数 -#define SKYWALKING_SPAN_LOG "lo"//Span 的日志 - - -int ski_zval_key = 0; -#define SKY_MAKE_NULL_ARRAY_NAME(i_zval_key) null_array_##i_zval_key +#define S_SEND_TYPE_CLOSE (1<<0L) +#define S_SEND_TYPE_GRPC (1<<1L) +#define S_SEND_TYPE_WRITE (1<<2L) + +#define USE_PARENT_TRACE_ID 1 +#define DONOT_USE_PARENT_TRACE_ID 0 + + + +#define SKYWALKING_SEGMENT "sg" //全部段节点 +#define SKYWALKING_DISTRIBUTED_TRACEIDS "gt"//DistributedTraceIds +#define SKYWALKING_TRACE_SEGMENT_ID "ts"//本次请求id +#define SKYWALKING_APPLICATION_ID "ai"//app id +#define SKYWALKING_APPLICATION_INSTANCE_ID "ii"//实例id +#define SKYWALKING_FATHER_NODE_DATA "rs" //父节点数据 +#define SKYWALKING_SPANS_NODE_DATA "ss" //span节点数据集合 + +#define SKYWALKING_PARENT_TRACE_SEGMENT_ID "ts" //本次请求id +#define SKYWALKING_PARENT_APPLICATION_ID "ai"//app id +#define SKYWALKING_PARENT_SPAN_ID "si"//spanid +#define SKYWALKING_PARENT_SERVICE_ID "vi"// +#define SKYWALKING_PARENT_SERVICE_NAME "vn" +#define SKYWALKING_NETWORK_ADDRESS_ID "ni" +#define SKYWALKING_NETWORK_ADDRESS "nn" +#define SKYWALKING_ENTRY_APPLICATION_INSTANCE_ID "ea" +#define SKYWALKING_ENTRY_SERVICE_ID "ei" +#define SKYWALKING_ENTRY_SERVICE_NAME "en" +#define SKYWALKING_REF_TYPE_VALUE "rv" + +#define SKYWALKING_SPAN_ID "si" //SpanId +#define SKYWALKING_SPAN_TYPE_VALUE "tv" +#define SKYWALKING_SPAN_LAYER_VALUE "lv" +#define SKYWALKING_FATHER_SPAN_ID "ps" //父节点传过来的SpanId +#define SKYWALKING_STARTTIME "st" //开始时间 +#define SKYWALKING_ENDTIME "et" //结束时间 +#define SKYWALKING_COMPONENT_ID "ci" +#define SKYWALKING_COMPONENT_NAME "cn" +#define SKYWALKING_OPERATION_NAME_ID "oi" +#define SKYWALKING_OPERATION_NAME "on"// Span 的服务URI +#define SKYWALKING_PEER_ID "pi" +#define SKYWALKING_PEER "pn" +#define SKYWALKING_IS_ERROR "ie" +#define SKYWALKING_TAGS "to" +#define SKYWALKING_LOGS "lo" + +#define SKYWALKING_KEY "k" +#define SKYWALKING_VALUE "v" + +#define SKYWALKING_TIME "ti" +#define SKYWALKING_LOG_DATA "ld" + + #define RAND_RANGE(__n, __min, __max, __tmax) \ (__n) = ((__min) + (zend_long) ((double) ( (double) (__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))) @@ -88,40 +121,54 @@ void *SKY_UPDATE_PROPERTY(zend_class_entry *cls, zval *tp, const char *name, siz array_init(&null_array); zend_update_property(cls, tp, name, name_length, &null_array); } + +static void *write_log_text(char *text); static char *sky_json_encode(zval *parameter); -static int _php_filter_validate_domain(char * domain, int len, zend_long flags) ; -static int _php_filter_validate_ipv4(char *str, size_t str_len, int *ip); -static int _php_filter_validate_ipv6(char *str, size_t str_len); -static int _php_filter_validate_url(char *value); -static zval *sky_instance(zval *this_ptr, const char *appCode); -static void date_register_classes(TSRMLS_D); -static void _init(const char *appCode, zval *this_ptr); -static char *build_SWheader_value(const char *peer_host, zval *this_ptr); -static zval *receive_SWHeader_from_caller(zval *this_ptr); +static char *build_SWheader_value(const char *peer_host); +static zval receive_SWHeader_from_caller(); static char *get_millisecond(); static char *uniqid(); static char *make_trace_id(); -static zend_always_inline zend_uchar is_sampling(zval *this_ptr); -static char *generate_trace_id(zval *this_ptr); +static zend_always_inline zend_uchar is_sampling(); +static char *generate_trace_id(); static char *get_ip(); static char *get_page_url_and_peer(); -static long generate_span_id(zval *this_ptr); -static char *generate_distributed_trace_ids(zval *this_ptr); -static void *write_log(zval *this_ptr, char *text); -static zval *set_span_nodes_data(zval *this_ptr, zval *node_data); -static char *sky_finishAll(); +static long generate_span_id(); +static void *write_log( char *text); +static zval *set_span_nodes_data(zval *node_data); static long sky_array_unshift(zval *stack, zval *var); -static void set_sampling_rate(zval *this_ptr, double degrees); -static void start_span_of_curl(char *peer_host, zval *headers, zval *this_pr); -static void set_span_param_of_curl(char *peer_host, zval *this_pr); -static void make_span_curl_header(char *peer_host, zval *headers, zval *this_pr); +static void set_sampling_rate(double degrees); +static void set_span_param_of_curl(char *peer_host); +static void make_span_curl_header(char *peer_host, zval *headers); static void start_span(zval *this_pr); static int is_auto_open(); -static void end_span_of_curl(zval *this_ptr,zval *curl); + void accel_sky_curl_init(INTERNAL_FUNCTION_PARAMETERS); void accel_sky_curl_setopt(INTERNAL_FUNCTION_PARAMETERS); void accel_sky_curl_exec(INTERNAL_FUNCTION_PARAMETERS); - +void list_poll(comList* myroot); + +static void *sky_flush_all(); +static char* _get_current_machine_ip(); +static int get_app_instance_id(); +static int get_app_id(); +static char *generate_parent_info_from_header(char *header_name); +static void start_node_span_of_curl(); +static char *generate_parent_trace_id(); +static zval* generate_trace_id_for_array(int use_parent_tid, zval* z_trace_id); +static char* _entry_app_name(); +static char *generate_distributed_trace_ids(); +static int _entry_app_instance_id(); +static void end_node_span_of_curl(zval *curl); +static void* send_grpc_param(zval *all_node_data); +static comList* create_com_list(); +static long _entry_app_name_operation_id(); +static long _parent_appname_operation_id(); +static int sky_live_pthread(pthread_t tid); +static int add_com_list(comList *com_list, UniqueIdStruct* data); +static void (*orig_curl_init)(INTERNAL_FUNCTION_PARAMETERS) = NULL; +static void (*orig_curl_setopt)(INTERNAL_FUNCTION_PARAMETERS) = NULL; +static void (*orig_curl_exec)(INTERNAL_FUNCTION_PARAMETERS) = NULL; /* Declare any global variables you may need between the BEGIN and END macros here: @@ -130,8 +177,10 @@ ZEND_BEGIN_MODULE_GLOBALS(skywalking) char *global_log_path; char *global_header_client_ip_name; char *global_app_code; + long global_send_type; zend_bool global_auto_open; double global_sampling_rate; + char *global_app_grpc_trace; ZEND_END_MODULE_GLOBALS(skywalking) extern ZEND_DECLARE_MODULE_GLOBALS(skywalking); @@ -146,6 +195,41 @@ extern ZEND_DECLARE_MODULE_GLOBALS(skywalking); ZEND_TSRMLS_CACHE_EXTERN() #endif + +#ifdef __unix + + +#ifdef __linux +#define SKY_OS_NAME "Linux" +#endif + +#ifdef __sun + #ifdef __sparc +#define SKY_OS_NAME "Sun SPARC" + #else +#define SKY_OS_NAME "Sun X86" + #endif +#endif + +#ifdef _AIX +#define SKY_OS_NAME "AIX" +#endif + + +#else + + +#ifdef WINVER +#define SKY_OS_NAME "Windows" +#else +#define SKY_OS_NAME "Unknown" +#endif + + +#endif + + + #endif /* PHP_SKYWALKING_H */ diff --git a/sky-php7ext/protos/ApplicationRegisterService.proto b/sky-php7ext/protos/ApplicationRegisterService.proto new file mode 100644 index 0000000000000000000000000000000000000000..567f6e66cacad229fddc444bb27cc732e1691346 --- /dev/null +++ b/sky-php7ext/protos/ApplicationRegisterService.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "org.apache.skywalking.apm.network.proto"; + + +//register service for ApplicationCode, this service is called when service starts. +service ApplicationRegisterService { + rpc applicationCodeRegister (Application) returns (ApplicationMapping) { + } +} + +message KeyWithIntegerValue { + string key = 1; + int32 value = 2; +} + +message Application { + string applicationCode = 1; +} + +message ApplicationMapping { + KeyWithIntegerValue application = 1; +} diff --git a/sky-php7ext/protos/DiscoveryService.proto b/sky-php7ext/protos/DiscoveryService.proto new file mode 100644 index 0000000000000000000000000000000000000000..7d4d57585d9255c52d1728dbbe2403ce347d01cb --- /dev/null +++ b/sky-php7ext/protos/DiscoveryService.proto @@ -0,0 +1,65 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "org.apache.skywalking.apm.network.proto"; + + +service InstanceDiscoveryService { + rpc registerInstance (ApplicationInstance) returns (ApplicationInstanceMapping) { + } +} + +message ApplicationInstance { + int32 applicationId = 1; + string agentUUID = 2; + int64 registerTime = 3; + OSInfo osinfo = 4; +} + +message ApplicationInstanceMapping { + int32 applicationId = 1; + int32 applicationInstanceId = 2; +} + +message ApplicationInstanceRecover { + int32 applicationId = 1; + int32 applicationInstanceId = 2; + int64 registerTime = 3; + OSInfo osinfo = 4; +} + +message ApplicationInstanceHeartbeat { + int32 applicationInstanceId = 1; + int64 heartbeatTime = 2; +} + +message OSInfo { + string osName = 1; + string hostname = 2; + int32 processNo = 3; + repeated string ipv4s = 4; +} + +//discovery service for ServiceName by Network address or application code +service ServiceNameDiscoveryService { + rpc discovery (ServiceNameCollection) returns (ServiceNameMappingCollection) { + } +} + +message ServiceNameCollection { + repeated ServiceNameElement elements = 1; +} + +message ServiceNameMappingCollection { + repeated ServiceNameMappingElement elements = 1; +} + +message ServiceNameMappingElement { + int32 serviceId = 1; + ServiceNameElement element = 2; +} + +message ServiceNameElement { + string serviceName = 1; + int32 applicationId = 2; +} diff --git a/sky-php7ext/protos/TraceSegmentService.proto b/sky-php7ext/protos/TraceSegmentService.proto new file mode 100644 index 0000000000000000000000000000000000000000..8b8aa512bbc87f413707073a257f468b2378f0aa --- /dev/null +++ b/sky-php7ext/protos/TraceSegmentService.proto @@ -0,0 +1,93 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "org.apache.skywalking.apm.network.proto"; + + +service TraceSegmentService { + rpc collect (stream UpstreamSegment) returns (Downstream) { + } +} + +message Downstream { +} + +message KeyWithStringValue { + string key = 1; + string value = 2; +} + +message UpstreamSegment { + repeated UniqueId globalTraceIds = 1; + bytes segment = 2; // the byte array of TraceSegmentObject +} + +message UniqueId { + repeated int64 idParts = 1; +} + +message TraceSegmentObject { + UniqueId traceSegmentId = 1; + repeated SpanObject spans = 2; + int32 applicationId = 3; + int32 applicationInstanceId = 4; + bool isSizeLimited = 5; +} + +message TraceSegmentReference { + RefType refType = 1; + UniqueId parentTraceSegmentId = 2; + int32 parentSpanId = 3; + int32 parentApplicationInstanceId = 4; + string networkAddress = 5; + int32 networkAddressId = 6; + int32 entryApplicationInstanceId = 7; + string entryServiceName = 8; + int32 entryServiceId = 9; + string parentServiceName = 10; + int32 parentServiceId = 11; +} + +message SpanObject { + int32 spanId = 1; + int32 parentSpanId = 2; + int64 startTime = 3; + int64 endTime = 4; + repeated TraceSegmentReference refs = 5; + int32 operationNameId = 6; + string operationName = 7; + int32 peerId = 8; + string peer = 9; + SpanType spanType = 10; + SpanLayer spanLayer = 11; + int32 componentId = 12; + string component = 13; + bool isError = 14; + repeated KeyWithStringValue tags = 15; + repeated LogMessage logs = 16; +} + +enum RefType { + CrossProcess = 0; + CrossThread = 1; +} + +enum SpanType { + Entry = 0; + Exit = 1; + Local = 2; +} + +enum SpanLayer { + Unknown = 0; + Database = 1; + RPCFramework = 2; + Http = 3; + MQ = 4; + Cache = 5; +} + +message LogMessage { + int64 time = 1; + repeated KeyWithStringValue data = 2; +} diff --git a/sky-php7ext/skywalking.c b/sky-php7ext/skywalking.c index d085a230b92a0e95aa2191f3b8e0ccb9cf18a361..1e5bf93f61922156bfe4df4eb464db16adc208dc 100644 --- a/sky-php7ext/skywalking.c +++ b/sky-php7ext/skywalking.c @@ -30,6 +30,7 @@ #include "php_ini.h" #include "ext/standard/info.h" #include "ext/standard/php_string.h" +#include "grpc/common_struct.h" #include "php_skywalking.h" #include "ext/standard/url.h" /* for php_url */ @@ -41,19 +42,33 @@ #include #include -static void (*orig_curl_init)(INTERNAL_FUNCTION_PARAMETERS) = NULL; -static void (*orig_curl_setopt)(INTERNAL_FUNCTION_PARAMETERS) = NULL; -static void (*orig_curl_exec)(INTERNAL_FUNCTION_PARAMETERS) = NULL; -/* If you declare any globals in php_skywalking.h uncomment this: +#include +#include +#include +#include +#include +#include +#include +#include + +extern int goSkyGrpc(char*host, int method, ParamDataStruct* paramData, void (*callfuct)( AppInstance* ) ); + +/* If you declare any globals in php_skywalking.h uncomment this: */ ZEND_DECLARE_MODULE_GLOBALS(skywalking) /* True global resources - no need for thread safety here */ static int le_skywalking; -char super_peer_host[50]; -int is_send_curl_header = 0; -zval super_curl_header; +static zval glob_skywalking_globals_list, glob_skywalking_globals_queue; +static char super_peer_host[50]; +static int is_send_curl_header = 0; +static zval super_curl_header; +static AppInstance appInstance; +static int sky_close = 0; +static int sky_increment_id = 0; +static long percent_int; +pthread_t pid_consumer; /* {{{ arginfo */ ZEND_BEGIN_ARG_INFO_EX(arginfo_sky_create, 0, 0, 1) @@ -71,315 +86,31 @@ ZEND_END_ARG_INFO() + /* {{{ PHP_INI */ /* Remove comments and fill if you need to have entries in php.ini*/ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("skywalking.auto_open", "1", PHP_INI_ALL, OnUpdateBool, global_auto_open, zend_skywalking_globals, skywalking_globals) STD_PHP_INI_ENTRY("skywalking.app_code", "", PHP_INI_ALL, OnUpdateString, global_app_code, zend_skywalking_globals, skywalking_globals) - STD_PHP_INI_ENTRY("skywalking.sampling_rate", "100", PHP_INI_ALL, OnUpdateReal, global_sampling_rate, zend_skywalking_globals, skywalking_globals) STD_PHP_INI_ENTRY("skywalking.log_path", "/tmp", PHP_INI_ALL, OnUpdateString, global_log_path, zend_skywalking_globals, skywalking_globals) + STD_PHP_INI_ENTRY("skywalking.send_type", "0", PHP_INI_ALL, OnUpdateLong, global_send_type, zend_skywalking_globals, skywalking_globals) + STD_PHP_INI_ENTRY("skywalking.sampling_rate", "/tmp", PHP_INI_ALL, OnUpdateString, global_sampling_rate, zend_skywalking_globals, skywalking_globals) STD_PHP_INI_ENTRY("skywalking.header_client_ip_name", "api", PHP_INI_ALL, OnUpdateString, global_header_client_ip_name, zend_skywalking_globals, skywalking_globals) + STD_PHP_INI_ENTRY("skywalking.grpc_trace", "127.0.0.1:50051", PHP_INI_ALL, OnUpdateString, global_app_grpc_trace, zend_skywalking_globals, skywalking_globals) + PHP_INI_END() /* }}} */ -/* Remove the following function when you have successfully modified config.m4 - so that your module can be compiled into PHP, it exists only for testing - purposes. */ - - -zend_class_entry *skywalking_ce_entry; -zval sky_t_ptr; - -/* Every user-visible function in PHP should document itself in the source */ -/* {{{ proto string confirm_skywalking_compiled(string arg) - Return a string to confirm that the module is compiled in */ -PHP_FUNCTION(confirm_skywalking_compiled) -{ - - char *arg = NULL; - size_t arg_len, len; - zend_string *strg; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg, &arg_len) == FAILURE) { - return; - } - - strg = strpprintf(0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "skywalking", arg); - - RETURN_STR(strg); -} - -PHP_METHOD(SkyWalking, __construct){ - - -} -PHP_METHOD(SkyWalking, startSpan){ -} -PHP_METHOD(SkyWalking, endSpan){ -} -PHP_METHOD(SkyWalking, setLogPath){ - - char *log_path; - long log_path_len; - zval *this_pr ; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &log_path, &log_path_len) == FAILURE) { - return; - } - this_pr = getThis(); - - zend_update_property_string(skywalking_ce_entry, this_pr, ZEND_STRL("_logPath"), log_path); - - RETURN_ZVAL(this_pr, 1, 0); -} -PHP_METHOD(SkyWalking, getInstance){ - char *appCode; - long appCode_len; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &appCode, &appCode_len) == FAILURE) { - return; - } - - zval *instance, rv = {{0}}; - if ((instance = sky_instance(&rv, appCode)) != NULL) { - ZVAL_COPY(&sky_t_ptr, instance); - RETURN_ZVAL(instance, 1, 0); - } -} - -PHP_METHOD(SkyWalking, setSamplingRate){ - double degrees; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "d", °rees) == FAILURE) { - return; - } - - zval *this_ptr ; - this_ptr = getThis(); - set_sampling_rate(this_ptr, degrees); - - - RETURN_ZVAL(this_ptr, 1, 0); -} -PHP_METHOD(SkyWalking, startSpanOfCurl){ - - char *peer_host; - zval *headers; - long peer_host_len,headers_len; - zval *this_pr ; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz", &peer_host, &peer_host_len, &headers) == FAILURE) { - return; - } - this_pr = getThis(); - start_span(this_pr); - set_span_param_of_curl(peer_host, this_pr); - Z_ADDREF_P(headers); - make_span_curl_header(peer_host, headers, this_pr); - - RETURN_ZVAL(this_pr, 1, 0); -} - - - - -PHP_METHOD(SkyWalking, endSpanOfCurl){ - - zval *this_ptr, *curl ; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &curl) == FAILURE) { - return; - } - - this_ptr = getThis(); - end_span_of_curl(this_ptr, curl); - - RETURN_ZVAL(this_ptr, 1, 0); -} - -PHP_METHOD(SkyWalking, __finishAll){ - char *results; - results = sky_finishAll(); - RETVAL_STRING(results); -} - - -static void start_span(zval *this_pr){ - - if(this_pr == NULL || is_sampling(this_pr) == IS_FALSE){ - return ; - } - - zval span_node_data, *z_span_node_data_struct; - zval z_span_id, millisecond; - z_span_node_data_struct = zend_read_property(skywalking_ce_entry, this_pr, ZEND_STRL("_spanNodeDataStruct"), 1, NULL); - array_init(&span_node_data); - zend_hash_copy(Z_ARRVAL(span_node_data), Z_ARRVAL_P(z_span_node_data_struct), (copy_ctor_func_t) zval_add_ref); - - ZVAL_LONG(&z_span_id, generate_span_id(this_pr)); - char *l_millisecond = get_millisecond(); - ZVAL_LONG(&millisecond, zend_atol(l_millisecond, strlen(l_millisecond))); - - zend_hash_str_update(Z_ARRVAL(span_node_data), SKYWALKING_SPAN_ID, sizeof(SKYWALKING_SPAN_ID) - 1, &z_span_id); - zend_hash_str_update(Z_ARRVAL(span_node_data), SKYWALKING_FATHER_SPAN_ID, sizeof(SKYWALKING_FATHER_SPAN_ID) - 1, - zend_hash_str_find(Z_ARRVAL_P(zend_read_property(skywalking_ce_entry, this_pr, ZEND_STRL("_spanFirstNodeData"), 1, NULL)), - ZEND_STRL(SKYWALKING_SPAN_ID))); - zend_hash_str_update(Z_ARRVAL(span_node_data), SKYWALKING_STARTTIME, sizeof(SKYWALKING_STARTTIME) - 1, &millisecond); - - zend_update_property(skywalking_ce_entry, this_pr, ZEND_STRL("_spanNodeData"), &span_node_data); -} - -static void set_span_param_of_curl(char *peer_host, zval *this_pr) -{ - if(this_pr == NULL || is_sampling(this_pr) == IS_FALSE){ - return ; - } - - zval *span_int_param, *span_node_data, *span_string_param; - span_node_data = zend_read_property(skywalking_ce_entry, this_pr, ZEND_STRL("_spanNodeData"), 1, NULL); - span_int_param = zend_hash_find(Z_ARRVAL_P(span_node_data), zend_string_init(ZEND_STRL(SKYWALKING_SPAN_INT_PARAM), 0)); - span_string_param = zend_hash_find(Z_ARRVAL_P(span_node_data), zend_string_init(ZEND_STRL(SKYWALKING_SPAN_STRING_PARAM), 0)); - add_assoc_string(span_string_param, "span.layer", "http"); - add_assoc_string(span_string_param, "component", "php-curl"); - add_assoc_string(span_string_param, "span.kind", "client"); - - int peer_port = 80 ; - zval *peer_port_z; - char *peer_host_s; - if(_php_filter_validate_url(peer_host)){ - php_url *url_info = php_url_parse(peer_host); - peer_host_s = url_info->host; - if(url_info->port){ - peer_port = url_info->port; - } - php_url_free(url_info); - }else{ - zval peer_host_array; - array_init(&peer_host_array); - zend_string *delim = zend_string_init(ZEND_STRL(":"), 0); - php_explode(delim, zend_string_init( peer_host, strlen(peer_host), 0), &peer_host_array, 5); - peer_host_s = Z_STRVAL_P(zend_hash_index_find(Z_ARRVAL(peer_host_array), 0)); - if((peer_port_z = zend_hash_index_find(Z_ARRVAL(peer_host_array), 1)) != NULL && Z_TYPE_P(peer_port_z) == IS_LONG){ - peer_port = Z_LVAL_P(peer_port_z); - } - } - add_assoc_string(span_string_param, "peer.host", peer_host_s); - add_assoc_long(span_int_param, "peer.port", (long)peer_port); -} - -static void make_span_curl_header(char *peer_host, zval *headers, zval *this_pr) -{ - char *headers_string, *tmp_headers_string; - tmp_headers_string = build_SWheader_value(peer_host, this_pr); - headers_string = (char *)emalloc(sizeof(char)*250); - sprintf(headers_string, "SWTraceContext: %s", tmp_headers_string); - add_next_index_string (headers, headers_string); - efree(headers_string); -} - - -static void end_span_of_curl(zval *this_ptr,zval *curl){ - - if(this_ptr == NULL){ - return ; - } - - - if(is_sampling(this_ptr) == IS_FALSE){ - return ; - } - - zval *span_node_data; - span_node_data = zend_read_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_spanNodeData"), 1, NULL); - - if(Z_TYPE_P(curl) != IS_RESOURCE || - strcmp( ZSTR_VAL(php_string_tolower(zend_string_init(ZEND_STRL(zend_rsrc_list_get_rsrc_type(Z_RES_P(curl))), 0))), "curl") != 0 ){ - zend_throw_exception(NULL, "Error :Need setting curl Object", 0); - } - zval function_name,curlInfo; - zval params[1]; - ZVAL_COPY(¶ms[0], curl); - ZVAL_STRING(&function_name, "curl_getinfo"); - call_user_function(CG(function_table), NULL, &function_name, &curlInfo, 1, params); - zval_ptr_dtor(¶ms[0]); - - - zval *span_string_param, *span_first_node_data, *span_int_param, *span_bool_param,null_oject; - zval *z_http_code; - zval millisecond; - char *l_millisecond = get_millisecond(); - ZVAL_LONG(&millisecond, zend_atol(l_millisecond, strlen(l_millisecond))); - - zend_hash_str_update(Z_ARRVAL_P(span_node_data), SKYWALKING_ENDTIME, sizeof(SKYWALKING_ENDTIME) - 1, &millisecond); - zend_hash_str_update(Z_ARRVAL_P(span_node_data), SKYWALKING_SPAN_SERVER_URI, sizeof(SKYWALKING_SPAN_SERVER_URI) - 1, - zend_hash_str_find(Z_ARRVAL(curlInfo), ZEND_STRL("url"))); - - z_http_code = zend_hash_str_find(Z_ARRVAL(curlInfo), ZEND_STRL("http_code")); - span_int_param = zend_hash_find(Z_ARRVAL_P(span_node_data), zend_string_init(ZEND_STRL(SKYWALKING_SPAN_INT_PARAM), 0)); - add_assoc_long(span_int_param, "status_code", Z_LVAL_P(z_http_code)); - - span_bool_param = zend_hash_find(Z_ARRVAL_P(span_node_data), zend_string_init(ZEND_STRL(SKYWALKING_SPAN_BOOL_PARAM), 0)); - if( Z_LVAL_P(z_http_code) !=200 ){ - add_assoc_string(span_bool_param, "error", "true"); - } - - if (span_bool_param == NULL || zend_hash_num_elements(Z_ARRVAL_P(span_bool_param)) == 0){ - object_init(&null_oject); - ZVAL_COPY(span_bool_param, &null_oject); - } - span_string_param = zend_hash_find(Z_ARRVAL_P(span_node_data), zend_string_init(ZEND_STRL(SKYWALKING_SPAN_STRING_PARAM), 0)); - span_int_param = zend_hash_find(Z_ARRVAL_P(span_node_data), zend_string_init(ZEND_STRL(SKYWALKING_SPAN_INT_PARAM), 0)); - add_assoc_string(span_string_param, "url", Z_STRVAL_P(zend_hash_str_find(Z_ARRVAL(curlInfo), ZEND_STRL("url")))); - - - set_span_nodes_data(this_ptr, span_node_data); -} - -static char *sky_finishAll(){ - - if(is_sampling(&sky_t_ptr) == IS_FALSE){ - return ""; - } - - zval *all_node_data, *span_first_node_data, *null_oject, span_bool_param, *span_int_param, *spans_node_data; - all_node_data = zend_read_property(skywalking_ce_entry, &sky_t_ptr, ZEND_STRL("_allNodeData"), 1, NULL); - zval *z_p_father_node_data = zend_hash_find(Z_ARRVAL_P(all_node_data), zend_string_init(ZEND_STRL(SKYWALKING_FATHER_NODE_DATA), 0)); - if (z_p_father_node_data == NULL || zend_hash_num_elements(Z_ARRVAL_P(z_p_father_node_data)) == 0){ - zend_hash_del(Z_ARRVAL_P(all_node_data), zend_string_init(ZEND_STRL(SKYWALKING_FATHER_NODE_DATA), 0)); - } - span_first_node_data = zend_read_property(skywalking_ce_entry, &sky_t_ptr, ZEND_STRL("_spanFirstNodeData"), 1, NULL); - char *l_millisecond = get_millisecond(); - add_assoc_long(span_first_node_data, SKYWALKING_ENDTIME, zend_atol(l_millisecond, strlen(l_millisecond))); - - object_init(&span_bool_param); - span_int_param = zend_hash_find(Z_ARRVAL_P( span_first_node_data), zend_string_init(ZEND_STRL(SKYWALKING_SPAN_INT_PARAM), 0)); - add_assoc_zval(span_first_node_data, SKYWALKING_SPAN_BOOL_PARAM, &span_bool_param); - add_assoc_long(span_int_param, "status_code", 200); - add_assoc_long(span_int_param, "peer.port", 80); - spans_node_data = zend_read_property(skywalking_ce_entry, &sky_t_ptr, ZEND_STRL("_spansNodeData"), 1, NULL); - - sky_array_unshift(spans_node_data, span_first_node_data); - char *l_f_millisecond = get_millisecond(); - add_assoc_long(all_node_data, SKYWALKING_ENDTIME, zend_atol(l_f_millisecond, strlen(l_f_millisecond))); - add_assoc_zval(all_node_data, SKYWALKING_SPANS_NODE_DATA, spans_node_data); - char *results; - results = sky_json_encode( all_node_data ); - - write_log(&sky_t_ptr, results); - - return results; -} - - - - - /* {{{ skywalking_functions[] * * Every user visible function must have an entry in skywalking_functions[]. */ const zend_function_entry skywalking_functions[] = { - PHP_FE(confirm_skywalking_compiled, NULL) /* For testing, remove later. */ + /* For testing, remove later. */ PHP_FE_END /* Must be the last line in skywalking_functions[] */ }; /* }}} */ @@ -387,18 +118,12 @@ const zend_function_entry skywalking_functions[] = { const zend_function_entry class_skywalking[] = { - PHP_ME(SkyWalking, __construct, arginfo_sky_create, ZEND_ACC_CTOR|ZEND_ACC_PRIVATE) - PHP_ME(SkyWalking, getInstance, arginfo_sky_void_arginfo, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) - PHP_ME(SkyWalking, startSpan, NULL, ZEND_ACC_PUBLIC ) - PHP_ME(SkyWalking, endSpan, NULL, ZEND_ACC_PUBLIC ) - PHP_ME(SkyWalking, setLogPath, NULL, ZEND_ACC_PUBLIC ) - PHP_ME(SkyWalking, setSamplingRate, NULL, ZEND_ACC_PUBLIC ) - PHP_ME(SkyWalking, startSpanOfCurl, NULL, ZEND_ACC_PUBLIC ) - PHP_ME(SkyWalking, endSpanOfCurl, NULL, ZEND_ACC_PUBLIC ) - PHP_ME(SkyWalking, __finishAll, NULL, ZEND_ACC_PUBLIC ) PHP_FE_END }; + + + /* The previous line is meant for vim and emacs, so it can correctly fold and unfold functions in source code. See the corresponding marks just before function definition, where the functions purpose is also documented. Please @@ -412,7 +137,6 @@ void accel_sky_curl_init(INTERNAL_FUNCTION_PARAMETERS) if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &url, &url_len) == FAILURE) { return; } - start_span(&sky_t_ptr); if( url != NULL ){ php_url *url_info = php_url_parse(url); char *peer_host_s; @@ -427,8 +151,8 @@ void accel_sky_curl_init(INTERNAL_FUNCTION_PARAMETERS) sprintf(super_peer_host, "%s", peer_host_s); } php_url_free(url_info); - set_span_param_of_curl(super_peer_host, &sky_t_ptr); } + start_node_span_of_curl(); orig_curl_init(INTERNAL_FUNCTION_PARAM_PASSTHRU); } @@ -438,12 +162,10 @@ void accel_sky_curl_setopt(INTERNAL_FUNCTION_PARAMETERS) zval *zid, *zvalue; zend_long options; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlz", &zid, &options, &zvalue) == FAILURE) { return; } - if( options == CURLOPT_URL ){ char *url = NULL; @@ -464,15 +186,14 @@ void accel_sky_curl_setopt(INTERNAL_FUNCTION_PARAMETERS) sprintf(super_peer_host, "%s", peer_host_s); } php_url_free(url_info); - set_span_param_of_curl(super_peer_host, &sky_t_ptr); } if( options == CURLOPT_HTTPHEADER ){ char *url = NULL; if( Z_TYPE_P(zvalue) != IS_ARRAY){ return ; } - if(super_peer_host != NULL){ - make_span_curl_header(super_peer_host, zvalue, &sky_t_ptr); + if(strlen(super_peer_host) != 0){ + make_span_curl_header(super_peer_host, zvalue); orig_curl_setopt(INTERNAL_FUNCTION_PARAM_PASSTHRU); is_send_curl_header = 1; } @@ -506,7 +227,7 @@ void accel_sky_curl_exec(INTERNAL_FUNCTION_PARAMETERS) zval_ptr_dtor(&super_curl_header); } orig_curl_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU); - end_span_of_curl(&sky_t_ptr, zid); + end_node_span_of_curl( zid ); } /* {{{ php_skywalking_init_globals */ @@ -515,74 +236,15 @@ static void php_skywalking_init_globals(zend_skywalking_globals *skywalking_glob { skywalking_globals->global_app_code = NULL; skywalking_globals->global_log_path = NULL; + skywalking_globals->global_sampling_rate = 99.22; skywalking_globals->global_auto_open = 1; + skywalking_globals->global_send_type = 1; skywalking_globals->global_header_client_ip_name = NULL; + skywalking_globals->global_app_grpc_trace = NULL; } -static long sky_array_unshift(zval *stack, zval *var) -{ - //7.0之前 - //php_splice(Z_ARRVAL_P(stack), 0, 0, args, argc, NULL TSRMLS_CC); - HashTable new_hash; /* New hashtable for the stack */ - - zend_string *key; - zval *value; - - - zend_hash_init(&new_hash, zend_hash_num_elements(Z_ARRVAL_P(stack)) + 1, NULL, ZVAL_PTR_DTOR, 0); - - zend_hash_next_index_insert_new(&new_hash, var); - if (EXPECTED(Z_ARRVAL_P(stack)->u.v.nIteratorsCount == 0)) { - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) { - if (key) { - zend_hash_add_new(&new_hash, key, value); - } else { - zend_hash_next_index_insert_new(&new_hash, value); - } - } ZEND_HASH_FOREACH_END(); - } else { - uint32_t old_idx; - uint32_t new_idx = 0; - uint32_t iter_pos = zend_hash_iterators_lower_pos(Z_ARRVAL_P(stack), 0); - - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) { - if (key) { - zend_hash_add_new(&new_hash, key, value); - } else { - zend_hash_next_index_insert_new(&new_hash, value); - } - old_idx = (Bucket*)value - Z_ARRVAL_P(stack)->arData; - if (old_idx == iter_pos) { - zend_hash_iterators_update(Z_ARRVAL_P(stack), old_idx, new_idx); - iter_pos = zend_hash_iterators_lower_pos(Z_ARRVAL_P(stack), iter_pos + 1); - } - new_idx++; - } ZEND_HASH_FOREACH_END(); - } - - - Z_ARRVAL_P(stack)->u.v.nIteratorsCount = 0; - Z_ARRVAL_P(stack)->pDestructor = NULL; - zend_hash_destroy(Z_ARRVAL_P(stack)); - - Z_ARRVAL_P(stack)->u.v.flags = new_hash.u.v.flags; - Z_ARRVAL_P(stack)->nTableSize = new_hash.nTableSize; - Z_ARRVAL_P(stack)->nTableMask = new_hash.nTableMask; - Z_ARRVAL_P(stack)->nNumUsed = new_hash.nNumUsed; - Z_ARRVAL_P(stack)->nNumOfElements = new_hash.nNumOfElements; - Z_ARRVAL_P(stack)->nNextFreeElement = new_hash.nNextFreeElement; - Z_ARRVAL_P(stack)->arData = new_hash.arData; - Z_ARRVAL_P(stack)->pDestructor = new_hash.pDestructor; - - zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack)); - - return zend_hash_num_elements(Z_ARRVAL_P(stack)); -} -/* }}} */ - - static char *sky_json_encode(zval *parameter){ int return_code; @@ -601,12 +263,98 @@ static char *sky_json_encode(zval *parameter){ return ZSTR_VAL(buf.s); } +static void make_span_curl_header(char *peer_host, zval *headers) +{ + char *headers_string, *tmp_headers_string; + tmp_headers_string = build_SWheader_value(peer_host); + headers_string = (char *)emalloc(sizeof(char)*250); + sprintf(headers_string, "sw3: %s", tmp_headers_string); + add_next_index_string (headers, headers_string); + efree(headers_string); +} + + + +static void in_queue_log(){ + + zval *all_node_data = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), ZEND_STRL("all_node_data")); + sky_array_unshift(&glob_skywalking_globals_queue, all_node_data); +} + + +static void* empty_consumer_thread_entry(zval* param) +{ + + zval *operand; + zend_string *string_key; + zend_ulong num_key; + int g_SegTypeVal = 15; + int num = 0; + + while( 1 ) + { + + if(zend_hash_num_elements(Z_ARRVAL(glob_skywalking_globals_queue)) > 0){ + ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL(glob_skywalking_globals_queue), num_key, string_key, operand) { + send_grpc_param(operand); + zend_hash_index_del(Z_ARRVAL(glob_skywalking_globals_queue), num_key); + } ZEND_HASH_FOREACH_END(); + } + + usleep( 1000 * g_SegTypeVal ); + } + + return NULL; +} + +static void* send_grpc_param(zval *all_node_data) +{ + zval *z_unique_id = zend_hash_str_find(Z_ARRVAL_P(all_node_data), ZEND_STRL(SKYWALKING_DISTRIBUTED_TRACEIDS)); + zval *operand; + zend_string *string_key; + zend_ulong num_key; + + TraceSegmentObjectStruct* traceSegment = (TraceSegmentObjectStruct *)malloc(sizeof(TraceSegmentObjectStruct)); + char *results = sky_json_encode( all_node_data ); + + char str_id_parts[20]; + long id_parts; + comList* com_list = create_com_list(); + + if(zend_hash_num_elements(Z_ARRVAL_P(z_unique_id)) > 0){ + ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(z_unique_id), num_key, string_key, operand) { + UniqueIdStruct *unique_id = (UniqueIdStruct *)malloc(sizeof(UniqueIdStruct)); + sprintf(str_id_parts, "%s", Z_STRVAL_P(operand)); + id_parts = zend_atol(str_id_parts, strlen(str_id_parts)); + unique_id->idParts = id_parts; + add_com_list(com_list, unique_id); + } ZEND_HASH_FOREACH_END(); + } + traceSegment->traceSegmentIdList = com_list; + traceSegment->segment = results; + ParamDataStruct* paramData; + paramData = (ParamDataStruct *)emalloc(sizeof(ParamDataStruct)); + paramData->sendTraceSegmentParam = (SendTraceSegmentParamStruct *)emalloc(sizeof(SendTraceSegmentParamStruct)); + paramData->sendTraceSegmentParam->traceSegment = traceSegment; + int global_send_type = SKY_G(global_send_type) ; + if( global_send_type & S_SEND_TYPE_WRITE ){ + write_log( results); + } + if( global_send_type & S_SEND_TYPE_GRPC ){ + goSkyGrpc( SKY_G(global_app_grpc_trace), METHOD__SEND_TRACE_SEGMENT, paramData, NULL); + } + efree(paramData->sendTraceSegmentParam); + efree(paramData); + free(traceSegment); +} + -static void *write_log(zval *this_ptr, char *text){ + +static void *write_log(char *text){ char *log_path; char logFilename[100]; char message[strlen(text)]; - log_path = Z_STRVAL_P(zend_read_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_logPath"), 1, NULL)); + log_path = SKY_G(global_log_path); zend_string *date_fmt; time_t t; @@ -621,442 +369,19 @@ static void *write_log(zval *this_ptr, char *text){ _php_error_log_ex(3, message, strlen(message) + 1, logFilename, NULL); } - -//移植过来的代码 -static int _php_filter_validate_url(char *value) /* {{{ */ +/** + * 获取接收到 SWTraceContext 的 header +// // */ +static zval receive_SWHeader_from_caller() { - - php_url *url; - zend_long flags = 0x2000000; - - - url = php_url_parse(value); - - if (url == NULL) { - return 0; - } - - if (url->scheme != NULL && (!strcasecmp(url->scheme, "http") || !strcasecmp(url->scheme, "https"))) { - char *e, *s, *t; - size_t l; - - if (url->host == NULL) { - goto bad_url; - } - - s = url->host; - l = strlen(s); - e = url->host + l; - t = e - 1; - - if (*s == '[' && *t == ']' && _php_filter_validate_ipv6((s + 1), l - 2)) { - php_url_free(url); - return 1; - } - - if (!_php_filter_validate_domain(url->host, l, 0x100000)) { - php_url_free(url); - return 0; - } - } - - if ( - url->scheme == NULL || - (url->host == NULL && (strcmp(url->scheme, "mailto") && strcmp(url->scheme, "news") && strcmp(url->scheme, "file"))) || - ((flags & 0x040000) && url->path == NULL) || ((flags & 0x080000) && url->query == NULL) - ) { -bad_url: - php_url_free(url); - return 0; - } - php_url_free(url); - return 1; -} -/* }}} */ - - - -static int _php_filter_validate_domain(char * domain, int len, zend_long flags) /* {{{ */ -{ - char *e, *s, *t; - size_t l; - int hostname = flags & 0x100000; - unsigned char i = 1; - - s = domain; - l = len; - e = domain + l; - t = e - 1; - - if (*t == '.') { - e = t; - l--; - } - - if (l > 253) { - return 0; - } - - if(*s == '.' || (hostname && !isalnum((int)*(unsigned char *)s))) { - return 0; - } - - while (s < e) { - if (*s == '.') { - if (*(s + 1) == '.' || (hostname && (!isalnum((int)*(unsigned char *)(s - 1)) || !isalnum((int)*(unsigned char *)(s + 1))))) { - return 0; - } - - i = 1; - } else { - if (i > 63 || (hostname && *s != '-' && !isalnum((int)*(unsigned char *)s))) { - return 0; - } - - i++; - } - - s++; - } - - return 1; -} -/* }}} */ - - - -static int _php_filter_validate_ipv4(char *str, size_t str_len, int *ip) /* {{{ */ -{ - - const char *end = str + str_len; - int num, m; - int n = 0; - - while (str < end) { - int leading_zero; - if (*str < '0' || *str > '9') { - return 0; - } - leading_zero = (*str == '0'); - m = 1; - num = ((*(str++)) - '0'); - while (str < end && (*str >= '0' && *str <= '9')) { - num = num * 10 + ((*(str++)) - '0'); - if (num > 255 || ++m > 3) { - return 0; - } - } - - if (leading_zero && (num != 0 || m > 1)) - return 0; - ip[n++] = num; - if (n == 4) { - return str == end; - } else if (str >= end || *(str++) != '.') { - return 0; - } - } - return 0; -} -/* }}} */ - - - -static int _php_filter_validate_ipv6(char *str, size_t str_len) /* {{{ */ -{ - int compressed = 0; - int blocks = 0; - int n; - char *ipv4; - char *end; - int ip4elm[4]; - char *s = str; - - if (!memchr(str, ':', str_len)) { - return 0; - } - - ipv4 = memchr(str, '.', str_len); - if (ipv4) { - while (ipv4 > str && *(ipv4-1) != ':') { - ipv4--; - } - - if (!_php_filter_validate_ipv4(ipv4, (str_len - (ipv4 - str)), ip4elm)) { - return 0; - } - - str_len = ipv4 - str; - if (str_len < 2) { - return 0; - } - - if (ipv4[-2] != ':') { - str_len--; - } - - blocks = 2; - } - - end = str + str_len; - - while (str < end) { - if (*str == ':') { - if (++str >= end) { - - return 0; - } - if (*str == ':') { - if (compressed) { - return 0; - } - blocks++; - compressed = 1; - - if (++str == end) { - return (blocks <= 8); - } - } else if ((str - 1) == s) { - return 0; - } - } - n = 0; - while ((str < end) && - ((*str >= '0' && *str <= '9') || - (*str >= 'a' && *str <= 'f') || - (*str >= 'A' && *str <= 'F'))) { - n++; - str++; - } - if (n < 1 || n > 4) { - return 0; - } - if (++blocks > 8) - return 0; - } - return ((compressed && blocks <= 8) || blocks == 8); -} -/* }}} */ - -static void date_register_classes(TSRMLS_D) -{ - - zend_class_entry ce_skywalking, ce_immutable, ce_timezone, ce_interval, ce_period, ce_interface; - - INIT_CLASS_ENTRY(ce_skywalking, "SkyWalking", class_skywalking); - skywalking_ce_entry = zend_register_internal_class_ex(&ce_skywalking, NULL); - - zend_declare_property_null(skywalking_ce_entry, ZEND_STRL("_instance"), ZEND_ACC_PROTECTED|ZEND_ACC_STATIC); - - zend_declare_property_string(skywalking_ce_entry, "_appCode", sizeof("_appCode")-1, "", ZEND_ACC_PRIVATE); - - zend_declare_property_null(skywalking_ce_entry, "_allPartsNodesStruct", sizeof("_allPartsNodesStruct")-1, ZEND_ACC_PRIVATE); - zend_declare_property_null(skywalking_ce_entry, "_fatherNodesStruct", sizeof("_fatherNodesStruct")-1, ZEND_ACC_PRIVATE); - zend_declare_property_null(skywalking_ce_entry, "_spanNodeDataStruct", sizeof("_spanNodeDataStruct")-1, ZEND_ACC_PRIVATE); - - - zend_declare_property_null(skywalking_ce_entry, "_allNodeData", sizeof("_allNodeData")-1, ZEND_ACC_PRIVATE); - zend_declare_property_null(skywalking_ce_entry, "_spansNodeData", sizeof("_spansNodeData")-1, ZEND_ACC_PRIVATE); - zend_declare_property_null(skywalking_ce_entry, "_fatherNodeData", sizeof("_fatherNodeData")-1, ZEND_ACC_PRIVATE); - zend_declare_property_null(skywalking_ce_entry, "_spanNodeData", sizeof("_spanNodeData")-1, ZEND_ACC_PRIVATE); - zend_declare_property_null(skywalking_ce_entry, "_spanFirstNodeData", sizeof("_spanFirstNodeData")-1, ZEND_ACC_PRIVATE); - zend_declare_property_null(skywalking_ce_entry, "_swHeaderInfo", sizeof("_swHeaderInfo")-1, ZEND_ACC_PRIVATE); - - zend_declare_property_null(skywalking_ce_entry, "_swHeaderText", sizeof("_swHeaderText")-1, ZEND_ACC_PRIVATE); - //唯一的事务编号 - zend_declare_property_null(skywalking_ce_entry, "_traceId", sizeof("_traceId")-1, ZEND_ACC_PRIVATE); - zend_declare_property_null(skywalking_ce_entry, "_distributedTraceIds", sizeof("_distributedTraceIds")-1, ZEND_ACC_PRIVATE); - //生产的SPAN_ID - zend_declare_property_long(skywalking_ce_entry, "_spanID", sizeof("_spanID")-1, 0, ZEND_ACC_PRIVATE); - //日志路径 - zend_declare_property_null(skywalking_ce_entry, "_logPath", sizeof("_logPath")-1, ZEND_ACC_PRIVATE); - //采样率 - zend_declare_property_null(skywalking_ce_entry, "_samplingRate", sizeof("_samplingRate")-1, ZEND_ACC_PRIVATE); - //本次进程是否采样 - zend_declare_property_null(skywalking_ce_entry, "_isSampling", sizeof("_isSampling")-1, ZEND_ACC_PRIVATE); -} -/* }}} */ - - -//实现单例 -static zval *sky_instance(zval *this_ptr, const char *appCode) /* {{{ */ { - - zval *instance; - //获取对象值 如果存在返回对象实例 - instance = zend_read_static_property(skywalking_ce_entry, ZEND_STRL("_instance"), 1); - if (IS_OBJECT == Z_TYPE_P(instance) - && instanceof_function(Z_OBJCE_P(instance), skywalking_ce_entry)) { - return instance; - } - //判断是否定义 - if (Z_ISUNDEF_P(this_ptr)) { - object_init_ex(this_ptr, skywalking_ce_entry); - } else { - return this_ptr; - } - _init(appCode, this_ptr); - - - return this_ptr; -} -/* }}} */ - -static void _init(const char *appCode, zval *this_ptr){ - - - //抛出异常 - if(appCode == NULL){ - zend_throw_exception(NULL, "Error : Must set appCode", 0); - } - //更新_appCode属性值 - zend_update_static_property(skywalking_ce_entry, ZEND_STRL("_instance"), this_ptr); - - zval allparts_property, father_property, span_property; - array_init(&allparts_property); - array_init(&father_property); - array_init(&span_property); - - /** - * 全部节点结构 - */ - add_assoc_null(&allparts_property, SKYWALKING_TRACEID); - - add_assoc_null(&allparts_property, SKYWALKING_STARTTIME); - add_assoc_null(&allparts_property, SKYWALKING_ENDTIME); - SKY_ADD_ASSOC_ZVAL(&allparts_property, SKYWALKING_FATHER_NODE_DATA); - SKY_ADD_ASSOC_ZVAL(&allparts_property, SKYWALKING_SPANS_NODE_DATA); - add_assoc_null(&allparts_property, SKYWALKING_APP_CODE); - add_assoc_null(&allparts_property, SKYWALKING_DISTRIBUTED_TRACEIDS); - zend_update_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_allPartsNodesStruct"), &allparts_property); - zval_ptr_dtor(&allparts_property); - - /** - * 父节点数据结构 - */ - add_assoc_null(&father_property, SKYWALKING_TRACEID); - add_assoc_null(&father_property, SKYWALKING_SPAN_ID); - add_assoc_null(&father_property, SKYWALKING_APP_CODE); - add_assoc_null(&father_property, SKYWALKING_PEERHOST); - zend_update_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_fatherNodesStruct"), &father_property); - zval_ptr_dtor(&father_property); - - - /** - * span节点结构 - */ - add_assoc_null(&span_property, SKYWALKING_SPAN_ID); - add_assoc_long(&span_property, SKYWALKING_FATHER_SPAN_ID, -1); - add_assoc_null(&span_property, SKYWALKING_STARTTIME); - add_assoc_null(&span_property, SKYWALKING_ENDTIME); - add_assoc_string(&span_property, SKYWALKING_SPAN_SERVER_URI, ""); - SKY_ADD_ASSOC_ZVAL(&span_property, SKYWALKING_SPAN_STRING_PARAM); - SKY_ADD_ASSOC_ZVAL(&span_property, SKYWALKING_SPAN_BOOL_PARAM); - SKY_ADD_ASSOC_ZVAL(&span_property, SKYWALKING_SPAN_INT_PARAM); - SKY_ADD_ASSOC_ZVAL(&span_property, SKYWALKING_SPAN_LOG); - - - zend_update_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_spanNodeDataStruct"), &span_property); - zval_ptr_dtor(&span_property); - - SKY_UPDATE_PROPERTY(skywalking_ce_entry, this_ptr, ZEND_STRL("_allNodeData")); - //span节点的集合 数组 - SKY_UPDATE_PROPERTY(skywalking_ce_entry, this_ptr, ZEND_STRL("_spansNodeData")); - //父节点数据 - SKY_UPDATE_PROPERTY(skywalking_ce_entry, this_ptr, ZEND_STRL("_fatherNodeData")); - //单个span节点数据 - SKY_UPDATE_PROPERTY(skywalking_ce_entry, this_ptr, ZEND_STRL("_spanNodeData")); - //第一个span节点数据 - SKY_UPDATE_PROPERTY(skywalking_ce_entry, this_ptr, ZEND_STRL("_spanFirstNodeData")); - - //kyWalking 包含的头信息 - SKY_UPDATE_PROPERTY(skywalking_ce_entry, this_ptr, ZEND_STRL("_swHeaderInfo")); - - zend_update_property_string(skywalking_ce_entry, this_ptr, ZEND_STRL("_appCode"), appCode); - - //对节点数据进行结构初始化 - zval *all_parts_nodes_struct, all_node_data; - all_parts_nodes_struct = zend_read_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_allPartsNodesStruct"), 1, NULL); - array_init(&all_node_data); - zend_hash_copy(Z_ARRVAL(all_node_data), Z_ARRVAL_P(all_parts_nodes_struct), (copy_ctor_func_t) zval_add_ref); - - receive_SWHeader_from_caller(this_ptr); - // //设置最开始的时间 - zval distributed_trace_ids_array; - char *distributed_trace_ids; - zval trace_id, all_millisecond; - - ZVAL_STRING(&trace_id, generate_trace_id(this_ptr)); - char *l_millisecond = get_millisecond(); - ZVAL_LONG(&all_millisecond, zend_atol(l_millisecond, strlen(l_millisecond))); - - zend_hash_str_update(Z_ARRVAL(all_node_data), SKYWALKING_TRACEID, sizeof(SKYWALKING_TRACEID) - 1, &trace_id); - zend_hash_str_update(Z_ARRVAL(all_node_data), SKYWALKING_STARTTIME, sizeof(SKYWALKING_STARTTIME) - 1, &all_millisecond); - zend_hash_str_update(Z_ARRVAL(all_node_data), SKYWALKING_APP_CODE, sizeof(SKYWALKING_APP_CODE) - 1, - zend_read_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_appCode"), 1, NULL)); - distributed_trace_ids = generate_distributed_trace_ids(this_ptr); - - array_init(&distributed_trace_ids_array); - add_index_string(&distributed_trace_ids_array, 0, distributed_trace_ids); - zend_hash_str_update(Z_ARRVAL(all_node_data), SKYWALKING_DISTRIBUTED_TRACEIDS, sizeof(SKYWALKING_DISTRIBUTED_TRACEIDS) - 1, &distributed_trace_ids_array); - zend_update_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_allNodeData"), &all_node_data); - /** - * 第一个span节点初始操作 - * 当前页 - */ - - char *page_url_and_peer; - zval span_first_node_data, span_string_param, *z_span_node_data_struct, z_page_url_and_peer; - z_span_node_data_struct = zend_read_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_spanNodeDataStruct"), 1, NULL); - - array_init(&span_first_node_data); - zend_hash_copy(Z_ARRVAL(span_first_node_data), Z_ARRVAL_P(z_span_node_data_struct), (copy_ctor_func_t) zval_add_ref); - - page_url_and_peer = get_page_url_and_peer(); - - ZVAL_STRING(&z_page_url_and_peer, page_url_and_peer); - - zend_string_init(page_url_and_peer, sizeof(page_url_and_peer) - 1, 0); - zval z_span_id; - zval first_millisecond; - char *l_f_millisecond = get_millisecond(); - - ZVAL_LONG(&first_millisecond, zend_atol(l_f_millisecond, strlen(l_f_millisecond))); - - ZVAL_LONG(&z_span_id, generate_span_id(this_ptr)); - zend_hash_str_update(Z_ARRVAL(span_first_node_data), SKYWALKING_SPAN_ID, sizeof(SKYWALKING_SPAN_ID) - 1, &z_span_id); - zend_hash_str_update(Z_ARRVAL(span_first_node_data), SKYWALKING_STARTTIME, sizeof(SKYWALKING_STARTTIME) - 1, &first_millisecond); - zend_hash_str_update(Z_ARRVAL(span_first_node_data), SKYWALKING_SPAN_SERVER_URI, sizeof(SKYWALKING_SPAN_SERVER_URI) - 1, &z_page_url_and_peer); - - array_init(&span_string_param); - - add_assoc_string(&span_string_param, "span.layer", "http"); - add_assoc_string(&span_string_param, "component", "php-server"); - add_assoc_string(&span_string_param, "peer.host", get_ip()); - add_assoc_string(&span_string_param, "url", page_url_and_peer); - add_assoc_string(&span_string_param, "span.kind", "server"); - zend_hash_str_update(Z_ARRVAL(span_first_node_data), SKYWALKING_SPAN_STRING_PARAM, sizeof(SKYWALKING_SPAN_STRING_PARAM) - 1, &span_string_param); - - zend_update_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_spanFirstNodeData"), &span_first_node_data); - - set_sampling_rate(this_ptr, SKY_G(global_sampling_rate)); - zend_update_property_string(skywalking_ce_entry, this_ptr, ZEND_STRL("_logPath"), SKY_G(global_log_path)); -} - - - -/** - * 获取接收到 SWTraceContext 的 header - */ -static zval *receive_SWHeader_from_caller(zval *this_ptr) -{ - zend_bool jit_initialization = PG(auto_globals_jit); - zval *ret; - zval *sw_header_info; - sw_header_info = zend_read_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_swHeaderInfo"), 1, NULL); - if (jit_initialization) { - zend_string *server_str = zend_string_init("_SERVER", sizeof("_SERVER") - 1, 0); - zend_is_auto_global(server_str); - zend_string_release(server_str); + zend_bool jit_initialization = PG(auto_globals_jit); + zval *ret; + zval sw_header_info; + array_init(&sw_header_info); + if (jit_initialization) { + zend_string *server_str = zend_string_init("_SERVER", sizeof("_SERVER") - 1, 0); + zend_is_auto_global(server_str); + zend_string_release(server_str); } if ((ret = zend_hash_str_find(Z_ARRVAL_P(zend_hash_str_find(&EG(symbol_table), ZEND_STRL("_SERVER"))), ZEND_STRL("HTTP_SWTRACECONTEXT"))) != NULL) { @@ -1074,16 +399,17 @@ static zval *receive_SWHeader_from_caller(zval *this_ptr) char *sw_header_info_keys[6] = {"TraceId", "SpanId", "AppCode", "PeerHost", "DistributedTraceIds", "IsSample"}; ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(&sw_header_info_z), num_key, string_key, operand) { - zend_hash_str_update(Z_ARRVAL_P(sw_header_info), sw_header_info_keys[num_key], strlen(sw_header_info_keys[num_key]), operand); + zend_hash_str_update(Z_ARRVAL(sw_header_info), sw_header_info_keys[num_key], strlen(sw_header_info_keys[num_key]), operand); } ZEND_HASH_FOREACH_END(); } + + add_assoc_zval(&glob_skywalking_globals_list, "_swHeaderInfo", &sw_header_info); return sw_header_info; } -static void set_sampling_rate(zval *this_ptr, double degrees){ +static void set_sampling_rate(double degrees){ - long percent_int; degrees = _php_math_round(degrees, 2, PHP_ROUND_HALF_UP); percent_int = (int)(degrees*100); @@ -1093,85 +419,114 @@ static void set_sampling_rate(zval *this_ptr, double degrees){ if(percent_int > 10000){ percent_int = 10000; } - zend_update_property_long(skywalking_ce_entry, this_ptr, ZEND_STRL("_samplingRate"), percent_int); + } +static zval* generate_trace_id_for_array(int use_parent_tid, zval* z_trace_id){ -static char *generate_trace_id(zval *this_ptr){ + char *trace_id = generate_trace_id(); + if(use_parent_tid){ + trace_id = generate_parent_trace_id(); + }else{ + trace_id = generate_trace_id(); + } + + + php_explode(zend_string_init(ZEND_STRL("."), 0), zend_string_init(trace_id, strlen(trace_id), 0), z_trace_id, 10); + return z_trace_id; +} + +static char *generate_parent_info_from_header(char *header_name){ + zval *ret; + zval *sw_header_info; + if( (sw_header_info = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), "_swHeaderInfo", sizeof("_swHeaderInfo") - 1)) != NULL){ + if ((ret = zend_hash_str_find(Z_ARRVAL_P(sw_header_info), header_name, sizeof(header_name) - 1)) != NULL) { + return Z_STRVAL_P(ret); + } + } + return NULL; +} + +static int have_parent_info_from_header(){ zval *sw_header_info; + if( (sw_header_info = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), "_swHeaderInfo", sizeof("_swHeaderInfo") - 1)) != NULL){ + if(zend_hash_num_elements(Z_ARRVAL_P(sw_header_info)) > 0){ + return 1; + } + } + return 0; +} + +static char *generate_parent_trace_id(){ zval *ret; - char *make_trace_id_c, *_trace_id; + zval *sw_header_info; + if( (sw_header_info = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), "_swHeaderInfo", sizeof("_swHeaderInfo") - 1)) != NULL){ + if ((ret = zend_hash_str_find(Z_ARRVAL_P(sw_header_info), "TraceId", sizeof("TraceId") - 1)) != NULL) { + return Z_STRVAL_P(ret); + } + } +} + +static char *generate_trace_id(){ + zval *sw_header_info, z__trace_id; + zval *ret; + char *_trace_id; _trace_id = (char *)emalloc(sizeof(char)*180); bzero(_trace_id, 180); - if( (sw_header_info = zend_read_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_swHeaderInfo"), 1, NULL)) != NULL){ + if( (sw_header_info = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), "_swHeaderInfo", sizeof("_swHeaderInfo") - 1)) != NULL){ if ((ret = zend_hash_str_find(Z_ARRVAL_P(sw_header_info), "TraceId", sizeof("TraceId") - 1)) != NULL) { + zend_hash_str_update(Z_ARRVAL(glob_skywalking_globals_list), "_traceId", sizeof("_traceId") - 1, ret); return Z_STRVAL_P(ret); } } - ret = zend_read_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_traceId"), 1, NULL); - if(Z_TYPE_P(ret) != IS_NULL){ + if ((ret = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), "_traceId", sizeof("_traceId") - 1)) != NULL) { return Z_STRVAL_P(ret); } - make_trace_id_c = make_trace_id(); - sprintf(_trace_id, "Segment.%s", make_trace_id_c); - zend_update_property_string(skywalking_ce_entry, this_ptr, ZEND_STRL("_traceId"), _trace_id); - efree(make_trace_id_c); + _trace_id = make_trace_id(); + ZVAL_STRING(&z__trace_id, _trace_id); + zend_hash_str_update(Z_ARRVAL(glob_skywalking_globals_list), "_traceId", sizeof("_traceId") - 1, &z__trace_id); + return _trace_id; } -static char *generate_distributed_trace_ids(zval *this_ptr){ +static char *generate_distributed_trace_ids(){ zval *sw_header_info; zval *ret; - char *make_trace_id_c, *_distributed_trace_ids; - _distributed_trace_ids = (char *)emalloc(sizeof(char)*180); - bzero(_distributed_trace_ids, 180); - if( (sw_header_info = zend_read_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_swHeaderInfo"), 1, NULL)) != NULL ){ + if( (sw_header_info = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), "_swHeaderInfo", sizeof("_swHeaderInfo") - 1)) != NULL){ if ((ret = zend_hash_str_find(Z_ARRVAL_P(sw_header_info), "DistributedTraceIds", sizeof("DistributedTraceIds") - 1)) != NULL) { return Z_STRVAL_P(ret); } } - - if(ret = zend_read_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_distributedTraceIds"), 1, NULL)); - if(Z_TYPE_P(ret) != IS_NULL){ - return Z_STRVAL_P(ret); + if ((ret = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), "DistributedTraceIds", sizeof("DistributedTraceIds") - 1)) != NULL) { + if(Z_TYPE_P(ret) != IS_NULL){ + return Z_STRVAL_P(ret); + } } - make_trace_id_c = make_trace_id(); - sprintf(_distributed_trace_ids, "Trace.%s", make_trace_id_c); - zend_update_property_string(skywalking_ce_entry, this_ptr, ZEND_STRL("_distributedTraceIds"), _distributed_trace_ids); - efree(make_trace_id_c); + + + char *_distributed_trace_ids; + _distributed_trace_ids = (char *)emalloc(sizeof(char)*180); + bzero(_distributed_trace_ids, 180); + _distributed_trace_ids = make_trace_id(); + add_assoc_string(&glob_skywalking_globals_list, "DistributedTraceIds", _distributed_trace_ids); + return _distributed_trace_ids; } static char *make_trace_id(){ - //生产唯一码毫秒时间戳.uuid.当前进程号PID.当前线程ID.当前线程生成的流水号.ip - char *millisecond; - char *uuid; - char *ip; + int app_instance_id = get_app_instance_id(); + int sys_pid = getpid(); + char *millisecond = get_millisecond(); char *makeTraceId; - zval *carrier = NULL; - zval *server_addr,*local_addr; - millisecond = get_millisecond(); - uuid = uniqid(); makeTraceId = (char *)emalloc(sizeof(char)*180); - bzero(makeTraceId, 180); - if (strcasecmp("cli", sapi_module.name) == 0){ - ip = "127.0.0.1"; - }else{ - carrier = &PG(http_globals)[TRACK_VARS_SERVER]; - if ((server_addr = zend_hash_str_find(Z_ARRVAL_P(carrier), "SERVER_ADDR", sizeof("SERVER_ADDR") - 1)) != NULL){ - ip = Z_STRVAL_P(server_addr); - }else { - local_addr = zend_hash_str_find(Z_ARRVAL_P(carrier), "LOCAL_ADDR", sizeof("LOCAL_ADDR") - 1); - ip = Z_STRVAL_P(local_addr); - } - } - sprintf(makeTraceId, "%s.%s.%d.0.0.%s", millisecond, uuid, getpid(), ip); - - efree(millisecond); - efree(uuid); + + bzero(makeTraceId, 80); + + sprintf(makeTraceId, "%d.%d.%s%d", app_instance_id, sys_pid, millisecond, sky_increment_id); + return makeTraceId; } @@ -1188,24 +543,6 @@ static char *get_millisecond(){ return buffer; } -static char *uniqid(){ - char *uniqid; - int sec, usec; - struct timeval tv; - uniqid = (char *)emalloc(sizeof(char)*20); - bzero(uniqid, 20); - gettimeofday((struct timeval *) &tv, (struct timezone *) NULL); - sec = (int) tv.tv_sec; - usec = (int) (tv.tv_usec % 0x100000); - - /* The max value usec can have is 0xF423F, so we use only five hex - * digits for usecs. - */ - sprintf(uniqid, "%08x%05x", sec, usec); - - return uniqid; -} - static char *get_page_url_and_peer(){ @@ -1235,118 +572,149 @@ static char *get_page_url_and_peer(){ } +static char *build_SWheader_value(const char *peer_host){ -static char *get_ip(){ - - zval *server_addr; - char *ip, *ip_x; - zval ip_z; - zval *carrier = NULL; - ip_x = (char *)emalloc(sizeof(char)*20); - ip = (char *)emalloc(sizeof(char)*100); - - bzero(ip_x, 20); - bzero(ip, 100); - carrier = &PG(http_globals)[TRACK_VARS_SERVER]; - if (strcasecmp("cli", sapi_module.name) == 0){ - strcpy(ip, "127.0.0.1"); - }else if(server_addr = zend_hash_str_find(Z_ARRVAL_P(carrier), SKY_G(global_header_client_ip_name), sizeof(SKY_G(global_header_client_ip_name)) - 1)){ - ip = Z_STRVAL_P(server_addr); - }else if(server_addr = zend_hash_str_find(Z_ARRVAL_P(carrier), "HTTP_X_FORWARDED_FOR", sizeof("HTTP_X_FORWARDED_FOR") - 1)){ - ip = Z_STRVAL_P(server_addr); - }else if(server_addr = zend_hash_str_find(Z_ARRVAL_P(carrier), "HTTP_CLIENT_IP", sizeof("HTTP_CLIENT_IP") - 1)){ - ip = Z_STRVAL_P(server_addr); - }else if(server_addr = zend_hash_str_find(Z_ARRVAL_P(carrier), "REMOTE_ADDR", sizeof("REMOTE_ADDR") - 1)){ - ip = Z_STRVAL_P(server_addr); - } - - if(strstr(ip, ",") != NULL){ - array_init(&ip_z); - zend_string *delim = zend_string_init(ZEND_STRL(","), 0); - - php_explode(delim, zend_string_init(ip, strlen(ip), 0), &ip_z, 10); - - ip_x = Z_STRVAL_P(zend_hash_index_find(Z_ARRVAL_P(&ip_z), 0)); - }else{ - memcpy(ip_x, ip, strlen(ip)); - } - efree(ip); - return ip_x; -} - -static char *build_SWheader_value(const char *peer_host, zval *this_ptr){ - - char *trace_id, *app_code, *distributed_trace_ids,*SW_header; - int is_sample_int = 0; - long span_id; + char *trace_id, *app_code, *SW_header, *distributed_trace_ids; + int span_id, parent_app_instance_id, entry_app_instance_id, entry_appname_operation_id, parent_appname_operation_id; + char c_peer_host[55] ; //zval SW_trace_context; SW_header = (char *)emalloc(sizeof(char)*250); - trace_id = generate_trace_id(this_ptr); - span_id = generate_span_id(this_ptr); - app_code = Z_STRVAL_P(zend_read_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_appCode"), 1, NULL)); - distributed_trace_ids = generate_distributed_trace_ids(this_ptr); - if(is_sampling(this_ptr) == IS_TRUE){ - is_sample_int = 1; - } - sprintf(SW_header, "%s|%ld|%s|%s|%s|%d", trace_id, span_id, app_code, peer_host, distributed_trace_ids, is_sample_int); + trace_id = generate_trace_id(); + span_id = generate_span_id(); + parent_app_instance_id = get_app_instance_id(); + entry_app_instance_id = _entry_app_instance_id(); + app_code = SKY_G(global_app_code); + sprintf(c_peer_host, "#%s", peer_host); + entry_appname_operation_id = _entry_app_name_operation_id(); + parent_appname_operation_id = _parent_appname_operation_id(); + distributed_trace_ids = generate_distributed_trace_ids(); + + + sprintf(SW_header, "%s|%d|%d|%d|%s|%d|%d|%s", + trace_id, span_id, parent_app_instance_id, entry_app_instance_id, + c_peer_host, entry_appname_operation_id, parent_appname_operation_id, distributed_trace_ids + ); return SW_header; } -static long generate_span_id(zval *this_ptr){ +static long generate_span_id(){ + long span_id; - span_id = Z_LVAL_P(zend_read_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_spanID"), 1, NULL)); - zend_update_property_long(skywalking_ce_entry, this_ptr, ZEND_STRL("_spanID"), ++span_id); + zval *swheaderinfo = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), "_swHeaderInfo", sizeof("_swHeaderInfo") - 1); + if (swheaderinfo == NULL || zend_hash_num_elements(Z_ARRVAL_P(swheaderinfo)) == 0){ + span_id = 1; + }else{ + span_id = Z_LVAL_P(zend_hash_str_find(Z_ARRVAL_P(swheaderinfo), "SpanId", sizeof("SpanId") - 1)); + } + + if(!span_id){ + span_id = 1; + } + zval z_span_id; + ZVAL_LONG(&z_span_id, ++span_id); + zend_hash_str_update(Z_ARRVAL(glob_skywalking_globals_list), "_spanID", sizeof("_spanID") - 1, &z_span_id); + return span_id; } -static zend_always_inline zend_uchar is_sampling(zval *this_ptr){ +static zend_always_inline zend_uchar is_sampling(){ - zval *z_p_is_sampling , *sw_header_info,*z_h_is_sample, *sampling_rate; + zval *z_p_is_sampling , sampling_rate; int is_sampling_int; zend_long rand_val; - z_p_is_sampling = zend_read_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_isSampling"), 1, NULL); - if(ZVAL_IS_NULL(z_p_is_sampling)){ + z_p_is_sampling = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), "_isSampling", sizeof("_isSampling") - 1); + + if( z_p_is_sampling == NULL || ZVAL_IS_NULL(z_p_is_sampling) ){ is_sampling_int = 0; - sw_header_info = zend_read_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_swHeaderInfo"), 1, NULL); - if (sw_header_info && zend_hash_num_elements(Z_ARRVAL_P(sw_header_info))){ - z_h_is_sample = zend_hash_str_find(Z_ARRVAL_P(sw_header_info), ZEND_STRL("IsSample")); - if(z_h_is_sample && strcmp(Z_STRVAL_P(z_h_is_sample),"1") == 0 ){ - is_sampling_int = 1; - } - }else{ - sampling_rate = zend_read_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_samplingRate"), 1, NULL); - if(Z_LVAL_P(sampling_rate) < 10000){ + + ZVAL_LONG(&sampling_rate, percent_int); + + if(Z_LVAL(sampling_rate) < 10000){ #if PHP_VERSION_ID >= 71000 - rand_val = php_mt_rand_common(1, 10000); + rand_val = php_mt_rand_common(1, 10000); #else - if (!BG(mt_rand_is_seeded)) { - php_mt_srand(GENERATE_SEED()); - } - rand_val = (zend_long) (php_mt_rand() >> 1); - RAND_RANGE(rand_val, 1, 10000, PHP_MT_RAND_MAX); + if (!BG(mt_rand_is_seeded)) { + php_mt_srand(GENERATE_SEED()); + } + rand_val = (zend_long) (php_mt_rand() >> 1); + RAND_RANGE(rand_val, 1, 10000, PHP_MT_RAND_MAX); #endif - if(Z_LVAL_P(sampling_rate) >= rand_val){ - is_sampling_int = 1; - } + if(Z_LVAL(sampling_rate) >= rand_val){ + is_sampling_int = 1; } } - zend_update_property_bool(skywalking_ce_entry, this_ptr, ZEND_STRL("_isSampling"), is_sampling_int); + zval z_readonly; + ZVAL_BOOL(&z_readonly, is_sampling_int); + + zend_hash_str_update(Z_ARRVAL(glob_skywalking_globals_list), "_isSampling", sizeof("_isSampling") - 1, &z_readonly); + return Z_TYPE(z_readonly); } return Z_TYPE_P(z_p_is_sampling); } +static char* _entry_app_name(){ + if(have_parent_info_from_header()){ + return generate_parent_info_from_header("EntryAppname"); + }else{ + return SKY_G(global_app_code); + } +} -static zval *set_span_nodes_data(zval *this_ptr, zval *node_data){ - zval *spans_node_data; - spans_node_data = zend_read_property(skywalking_ce_entry, this_ptr, ZEND_STRL("_spansNodeData"), 1, NULL); - zend_hash_next_index_insert(Z_ARRVAL_P(spans_node_data), node_data); +static int _entry_app_instance_id(){ + if(have_parent_info_from_header()){ + char *parent_app_instance_id = generate_parent_info_from_header("EntryAppInstanceid"); + + return zend_atoi(parent_app_instance_id, (int)strlen(parent_app_instance_id)); + }else{ + return get_app_instance_id(); + } +} +static long _entry_app_name_operation_id(){ + if(have_parent_info_from_header()){ + char *app_name_operation_id = generate_parent_info_from_header("EntryAppnameOperationId"); + + return zend_atol(app_name_operation_id, (int)strlen(app_name_operation_id)); + }else{ + zval *span_first_node_data = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), ZEND_STRL("span_first_node_data")); + return Z_LVAL_P(zend_hash_str_find(Z_ARRVAL_P(span_first_node_data), ZEND_STRL(SKYWALKING_SPAN_ID))); + } +} + +static long _parent_appname_operation_id(){ + zval *span_first_node_data = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), ZEND_STRL("span_first_node_data")); + return Z_LVAL_P(zend_hash_str_find(Z_ARRVAL_P(span_first_node_data), ZEND_STRL(SKYWALKING_SPAN_ID))); +} + + + + +void set_app_instance_id( AppInstance* appInste ){ + if( appInste != NULL ){ + appInstance.applicationInstanceId = appInste->applicationInstanceId; + } + +} +void set_app_id( AppInstance* appInste ){ + if( appInste != NULL ){ + appInstance.applicationId = appInste->applicationId; + } +} + +static int get_app_instance_id(){ + return appInstance.applicationInstanceId; +} +static int get_app_id(){ + return appInstance.applicationId; } static int is_auto_open(){ + if(sky_close){ + return 0; + } if((strcasecmp("cli", sapi_module.name) != 0) && (SG(sapi_headers).http_response_code != 200)){ return 0; } @@ -1357,16 +725,334 @@ static int is_auto_open(){ } +/** + * 当前机器ip + * + * @since 2017年11月23日 + * @copyright + * @return return_type +// */ +static char* _get_current_machine_ip(){ + + + char *ip; + zval *carrier = NULL; + ip = (char *)emalloc(sizeof(char)*100); + + bzero(ip, 100); + + carrier = &PG(http_globals)[TRACK_VARS_SERVER]; + + if (strcasecmp("cli", sapi_module.name) == 0){ + strcpy(ip, "127.0.0.1"); + }else{ + char hname[128]; + struct hostent *hent; + gethostname(hname, sizeof(hname)); + hent = gethostbyname(hname); + ip = inet_ntoa(*(struct in_addr*)(hent->h_addr_list[0])); + } + + + return ip; +} + +static zval* get_father_node_data(zval* father_nodes_data){ + + + + if(!have_parent_info_from_header()){ + return NULL; + } + + zval z_trace_id; + array_init(&z_trace_id); + add_assoc_zval(father_nodes_data, SKYWALKING_PARENT_TRACE_SEGMENT_ID, generate_trace_id_for_array(USE_PARENT_TRACE_ID, &z_trace_id)); + + char *parent_app_instance_id = generate_parent_info_from_header("ParentAppInstanceid"); + add_assoc_long(father_nodes_data, SKYWALKING_PARENT_APPLICATION_ID, zend_atoi(parent_app_instance_id, str_len(parent_app_instance_id))); + + char *span_id = generate_parent_info_from_header("SpanId"); + add_assoc_long(father_nodes_data, SKYWALKING_PARENT_SPAN_ID, zend_atoi(span_id, str_len(span_id))); + add_assoc_string(father_nodes_data, SKYWALKING_PARENT_SERVICE_ID, generate_parent_info_from_header("ParentAppname")); + add_assoc_string(father_nodes_data, SKYWALKING_PARENT_SERVICE_NAME, generate_parent_info_from_header("ParentAppname")); + add_assoc_string(father_nodes_data, SKYWALKING_NETWORK_ADDRESS_ID, generate_parent_info_from_header("PeerHost")); + add_assoc_string(father_nodes_data, SKYWALKING_NETWORK_ADDRESS, generate_parent_info_from_header("PeerHost")); + add_assoc_string(father_nodes_data, SKYWALKING_PARENT_SERVICE_ID, generate_parent_info_from_header("ParentAppname")); + add_assoc_string(father_nodes_data, SKYWALKING_ENTRY_APPLICATION_INSTANCE_ID, generate_parent_info_from_header("EntryAppInstanceid")); + char *entry_app_id = generate_parent_info_from_header("EntryAppId"); + add_assoc_long(father_nodes_data, SKYWALKING_ENTRY_SERVICE_ID, zend_atoi(entry_app_id, str_len(entry_app_id))); + add_assoc_string(father_nodes_data, SKYWALKING_ENTRY_SERVICE_NAME, generate_parent_info_from_header("EntryAppname")); + add_assoc_long(father_nodes_data, SKYWALKING_REF_TYPE_VALUE, 0); + + return father_nodes_data; +} + +static zval *set_span_nodes_data(zval *node_data){ + zval *spans_node_data; + spans_node_data = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), ZEND_STRL("_spansNodeData")); + zend_hash_next_index_insert(Z_ARRVAL_P(spans_node_data), node_data); + zval_ptr_dtor(node_data); +} + +static void nodeinit(){ + + if(!sky_live_pthread(pid_consumer)){ + if (pthread_create(&pid_consumer, NULL, (void *) empty_consumer_thread_entry, NULL) < 0) + { + sky_close = 1; + return ; + } + } + zval glob_all_node_data, segment, span_first_node_data; + zval father_node_data; + array_init(&glob_all_node_data); + array_init(&span_first_node_data); + array_init(&segment); + array_init(&father_node_data); + + receive_SWHeader_from_caller(); + zval z_trace_id; + array_init(&z_trace_id); + generate_trace_id_for_array(DONOT_USE_PARENT_TRACE_ID, &z_trace_id); + add_assoc_zval(&glob_all_node_data, SKYWALKING_DISTRIBUTED_TRACEIDS, &z_trace_id); + + add_assoc_zval(&segment, SKYWALKING_TRACE_SEGMENT_ID, &z_trace_id); + + add_assoc_long(&segment, SKYWALKING_APPLICATION_ID, get_app_id()); + add_assoc_long(&segment, SKYWALKING_APPLICATION_INSTANCE_ID, get_app_instance_id()); + + get_father_node_data(&father_node_data); + + add_assoc_zval(&segment, SKYWALKING_FATHER_NODE_DATA, &father_node_data); + add_assoc_zval(&glob_all_node_data, SKYWALKING_SEGMENT, &segment); + + + add_assoc_long(&span_first_node_data, SKYWALKING_SPAN_ID, generate_span_id()); + + add_assoc_long(&span_first_node_data, SKYWALKING_SPAN_TYPE_VALUE, 0); + add_assoc_long(&span_first_node_data, SKYWALKING_SPAN_LAYER_VALUE, 3); + + char *l_millisecond = get_millisecond(); + long starttime = zend_atol(l_millisecond, strlen(l_millisecond)); + add_assoc_long(&span_first_node_data, SKYWALKING_STARTTIME, starttime); + add_assoc_long(&span_first_node_data, SKYWALKING_FATHER_SPAN_ID, -1); + + //add_assoc_string(&span_first_node_data, SKYWALKING_COMPONENT_ID, "php-server"); + add_assoc_string(&span_first_node_data, SKYWALKING_COMPONENT_NAME, "php-server"); + //add_assoc_string(&span_first_node_data, SKYWALKING_PEER_ID, "server"); + add_assoc_string(&span_first_node_data, SKYWALKING_PEER, "127.0.0.1"); + SKY_ADD_ASSOC_ZVAL(&span_first_node_data, SKYWALKING_LOGS); + + //add_assoc_string(&span_first_node_data, SKYWALKING_OPERATION_NAME_ID, get_page_url_and_peer()); + add_assoc_string(&span_first_node_data, SKYWALKING_OPERATION_NAME, get_page_url_and_peer()); + add_assoc_bool(&span_first_node_data, SKYWALKING_IS_ERROR, 0); + + zval t_tags, t_tags_tmp; + array_init(&t_tags); + array_init(&t_tags_tmp); + + zval z_url_k, z_url_v; + ZVAL_STRING(&z_url_k, "url"); + ZVAL_STRING(&z_url_v, get_page_url_and_peer()); + zend_hash_str_update(Z_ARRVAL(t_tags_tmp), "k", sizeof("k") - 1, &z_url_k); + zend_hash_str_update(Z_ARRVAL(t_tags_tmp), "v", sizeof("v") - 1, &z_url_v); + add_index_zval(&t_tags, 0, &t_tags_tmp); + add_assoc_zval(&span_first_node_data, SKYWALKING_TAGS, &t_tags); + + add_assoc_zval(&glob_skywalking_globals_list, "span_first_node_data", &span_first_node_data); + add_assoc_zval(&glob_skywalking_globals_list, "all_node_data", &glob_all_node_data); + + SKY_ADD_ASSOC_ZVAL(&glob_skywalking_globals_list, "_span_node_data"); + SKY_ADD_ASSOC_ZVAL(&glob_skywalking_globals_list, "_spansNodeData"); +} + + +static void start_node_span_of_curl(){ + + zval span_node_data, * z_span_id; + array_init(&span_node_data); + zval *span_first_node_data = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), ZEND_STRL("span_first_node_data")); + + add_assoc_long(&span_node_data, SKYWALKING_SPAN_ID, generate_span_id()); + add_assoc_long(&span_node_data, SKYWALKING_FATHER_SPAN_ID, Z_LVAL_P(zend_hash_str_find(Z_ARRVAL_P(span_first_node_data), ZEND_STRL(SKYWALKING_SPAN_ID)))); + + char *l_millisecond = get_millisecond(); + long starttime = zend_atol(l_millisecond, strlen(l_millisecond)); + add_assoc_long(&span_node_data, SKYWALKING_STARTTIME, starttime); + //add_assoc_string(&span_node_data, SKYWALKING_COMPONENT_ID, "php-server"); + add_assoc_string(&span_node_data, SKYWALKING_COMPONENT_NAME, "php-curl"); + add_assoc_long(&span_node_data, SKYWALKING_SPAN_TYPE_VALUE, 1); + add_assoc_long(&span_node_data, SKYWALKING_SPAN_LAYER_VALUE, 3); + + zend_hash_str_update(Z_ARRVAL(glob_skywalking_globals_list), "_span_node_data", sizeof("_span_node_data") - 1, &span_node_data); +} + +static void end_node_span_of_curl(zval *curl){ + + + zval *span_node_data; + span_node_data = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), ZEND_STRL("_span_node_data")); + + zval function_name,curlInfo; + zval params[1]; + ZVAL_COPY(¶ms[0], curl); + ZVAL_STRING(&function_name, "curl_getinfo"); + call_user_function(CG(function_table), NULL, &function_name, &curlInfo, 1, params); + zval_ptr_dtor(¶ms[0]); + + + zval *span_string_param, *span_first_node_data, *span_int_param, *span_bool_param,null_oject; + zval *z_http_code; + long millisecond; + char *l_millisecond = get_millisecond(); + millisecond = zend_atol(l_millisecond, strlen(l_millisecond)); + + zval *z_url = zend_hash_str_find(Z_ARRVAL(curlInfo), ZEND_STRL("url")); + + z_http_code = zend_hash_str_find(Z_ARRVAL(curlInfo), ZEND_STRL("http_code")); + zval t_tags, t_tags_tmp; + array_init(&t_tags); + array_init(&t_tags_tmp); + + zval z_url_k; + ZVAL_STRING(&z_url_k, "url"); + zend_hash_str_update(Z_ARRVAL(t_tags_tmp), "k", sizeof("k") - 1, &z_url_k); + zend_hash_str_update(Z_ARRVAL(t_tags_tmp), "v", sizeof("v") - 1, z_url); + add_index_zval(&t_tags, 0, &t_tags_tmp); + + add_assoc_long(span_node_data, SKYWALKING_ENDTIME, millisecond); + + php_url *url_info = php_url_parse( Z_STRVAL_P(z_url) ); + char peer_operation[200]; + + int peer_port = 0; + if(url_info->port){ + peer_port = url_info->port; + } + if(peer_port > 0){ + sprintf(peer_operation, "%s:%d%s", url_info->host, peer_port, url_info->path); + }else{ + sprintf(peer_operation, "%s%s", url_info->host, url_info->path); + } + php_url_free(url_info); + + //add_assoc_string(&span_node_data, SKYWALKING_PEER_ID, "server"); + add_assoc_string(span_node_data, SKYWALKING_PEER, super_peer_host); + add_assoc_string(span_node_data, SKYWALKING_OPERATION_NAME, peer_operation); + SKY_ADD_ASSOC_ZVAL(span_node_data, SKYWALKING_LOGS); + //add_assoc_string(span_node_data, SKYWALKING_OPERATION_NAME_ID, z_url); + + if( Z_LVAL_P(z_http_code) !=200 ){ + add_assoc_bool(span_node_data, SKYWALKING_IS_ERROR, 1); + }else{ + add_assoc_bool(span_node_data, SKYWALKING_IS_ERROR, 0); + } + + add_assoc_zval(span_node_data, SKYWALKING_TAGS, &t_tags); + set_span_nodes_data(span_node_data); + +} + + +static void *sky_flush_all(){ + zval *all_node_data, *span_first_node_data, *null_oject, span_bool_param, *span_int_param, *spans_node_data, *segment; + all_node_data = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), ZEND_STRL("all_node_data")); + segment = zend_hash_str_find(Z_ARRVAL_P(all_node_data), ZEND_STRL(SKYWALKING_SEGMENT)); + + zval *z_p_father_node_data = zend_hash_str_find(Z_ARRVAL_P(all_node_data), ZEND_STRL(SKYWALKING_FATHER_NODE_DATA)); + //if (z_p_father_node_data == NULL || zend_hash_num_elements(Z_ARRVAL_P(z_p_father_node_data)) == 0){ + // zend_hash_del(Z_ARRVAL_P(all_node_data), zend_string_init(ZEND_STRL(SKYWALKING_FATHER_NODE_DATA), 0)); + //} + + span_first_node_data = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), ZEND_STRL("span_first_node_data")); + char *l_millisecond = get_millisecond(); + add_assoc_long(span_first_node_data, SKYWALKING_ENDTIME, zend_atol(l_millisecond, strlen(l_millisecond))); + + spans_node_data = zend_hash_str_find(Z_ARRVAL(glob_skywalking_globals_list), ZEND_STRL("_spansNodeData")); + + sky_array_unshift(spans_node_data, span_first_node_data); + char *l_f_millisecond = get_millisecond(); + //add_assoc_long(all_node_data, SKYWALKING_ENDTIME, zend_atol(l_f_millisecond, strlen(l_f_millisecond))); + add_assoc_zval(segment, SKYWALKING_SPANS_NODE_DATA, spans_node_data); + + + in_queue_log(); +} + + +static void appinit(){ + + array_init(&glob_skywalking_globals_queue); + appInstance.applicationInstanceId = -100000; + appInstance.applicationId = -100000; + if (pthread_create(&pid_consumer, NULL, (void *) empty_consumer_thread_entry, NULL) < 0) + { + sky_close = 1; + return ; + } + + char* app_code = SKY_G(global_app_code); + char* ipv4s = _get_current_machine_ip(); + char agentUUID[80]; + ParamDataStruct* paramData; + paramData = (ParamDataStruct *)emalloc(sizeof(ParamDataStruct)); + paramData->registerParam = (RegisterParamtruct *)emalloc(sizeof(RegisterParamtruct)); + paramData->registerParam->appCode = app_code; + int stu = goSkyGrpc( SKY_G(global_app_grpc_trace), METHOD__GO_REGISTER, paramData, set_app_id); + if( stu == 0 || appInstance.applicationId == -100000){ + sky_close = 1; + return ; + } + strcat(agentUUID, app_code); + strcat(agentUUID, ipv4s); + + paramData->registerInstanceParam = (RegisterInstanceParamtruct *)emalloc(sizeof(RegisterInstanceParamtruct)); + paramData->registerInstanceParam->agentUUID = agentUUID; + paramData->registerInstanceParam->osName = SKY_OS_NAME; + char hostname[100] = {0}; + if(gethostname(hostname, sizeof(hostname)) < 0){ + strcpy(hostname, ""); + } + paramData->registerInstanceParam->ipv4s = ipv4s; + char *l_millisecond = get_millisecond(); + paramData->registerInstanceParam->registerTime = zend_atol(l_millisecond, strlen(l_millisecond)); + paramData->registerInstanceParam->processNo = getpid(); + paramData->registerInstanceParam->hostname = hostname; + paramData->registerInstanceParam->applicationId = appInstance.applicationId; + + + stu = goSkyGrpc( SKY_G(global_app_grpc_trace), METHOD__GO_REGISTER_INSTANCE, paramData, set_app_instance_id); + if( stu == 0 || appInstance.applicationInstanceId == -100000){ + //close skywalking + sky_close = 1; + return ; + } + efree( paramData->registerParam ); + efree( paramData ); +} + + /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(skywalking) { ZEND_INIT_MODULE_GLOBALS(skywalking, php_skywalking_init_globals, NULL); - date_register_classes(TSRMLS_C); + if(sky_close){ + return SUCCESS; + } + //data_register_hashtable(); REGISTER_INI_ENTRIES(); + /* If you have INI entries, uncomment these lines */ if(SKY_G(global_auto_open)){ + + appinit(); + if( sky_close == 1 ){ + return SUCCESS; + } + set_sampling_rate(SKY_G(global_sampling_rate)); zend_function *old_function; if ((old_function = zend_hash_str_find_ptr(CG(function_table), "curl_init", sizeof("curl_init")-1)) != NULL) { orig_curl_init = old_function->internal_function.handler; @@ -1399,19 +1085,23 @@ PHP_MSHUTDOWN_FUNCTION(skywalking) /* }}} */ /* Remove if there's nothing to do at request start */ -/* {{{ PHP_RINIT_FUNCTION +/* {{{ PHP_RINIT_FUNCTION7 */ PHP_RINIT_FUNCTION(skywalking) { + #if defined(COMPILE_DL_SKYWALKING) && defined(ZTS) ZEND_TSRMLS_CACHE_UPDATE(); #endif - if(is_auto_open()){ - zval *instance, rv = {{0}}; - if ((instance = sky_instance(&rv, SKY_G(global_app_code))) != NULL) { - ZVAL_COPY(&sky_t_ptr, instance); + array_init(&glob_skywalking_globals_list); + //&& is_sampling() == IS_TRUE + if( is_auto_open() ){ + sky_increment_id ++; + if(sky_increment_id >= 999999){ + sky_increment_id = 0; } + nodeinit(); } return SUCCESS; @@ -1424,10 +1114,9 @@ PHP_RINIT_FUNCTION(skywalking) PHP_RSHUTDOWN_FUNCTION(skywalking) { if(is_auto_open()){ - sky_finishAll(); + sky_flush_all(); } is_send_curl_header = 0; - //zend_hash_destroy(Z_ARRVAL(super_curl_header)); zval_ptr_dtor(&super_curl_header); array_init(&super_curl_header); @@ -1439,6 +1128,7 @@ PHP_RSHUTDOWN_FUNCTION(skywalking) */ PHP_MINFO_FUNCTION(skywalking) { + php_info_print_table_start(); php_info_print_table_header(2, "skywalking support", "enabled"); php_info_print_table_end(); @@ -1476,6 +1166,115 @@ zend_module_entry skywalking_module_entry = { }; /* }}} */ + + +/******************************************** transplantThe coming code *****************************************/ + +static comList* create_com_list(){ + comList *com_list = (comList *)malloc(sizeof(comList)); + memset(com_list, 0, sizeof(comList)); + com_list->count = 0 ; + com_list->head = NULL; + com_list->tail = NULL; + + return com_list; +} + +static int add_com_list(comList *com_list, UniqueIdStruct* data){ + + comListNode *com_list_node = (comListNode *)malloc(sizeof(comListNode));; + com_list_node->next = NULL; + com_list_node->data = data; + com_list->count ++; + if(com_list->head == NULL){ + com_list->head = com_list_node; + }else{ + com_list->tail->next = com_list_node; + } + com_list->tail = com_list_node; + return 1; +} + +static int sky_live_pthread(pthread_t tid) +{ + + int pthread_kill_err; + + pthread_kill_err = pthread_kill(tid, 0); + if(pthread_kill_err == ESRCH){ + return 0; + } else if(pthread_kill_err == EINVAL){ + return 0; + } else { + return 1; + } +} + +static long sky_array_unshift(zval *stack, zval *var) +{ + //7.0之前 + //php_splice(Z_ARRVAL_P(stack), 0, 0, args, argc, NULL TSRMLS_CC); + HashTable new_hash; /* New hashtable for the stack */ + + zend_string *key; + zval *value; + + + zend_hash_init(&new_hash, zend_hash_num_elements(Z_ARRVAL_P(stack)) + 1, NULL, ZVAL_PTR_DTOR, 0); + + zend_hash_next_index_insert_new(&new_hash, var); + if (EXPECTED(Z_ARRVAL_P(stack)->u.v.nIteratorsCount == 0)) { + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) { + if (key) { + zend_hash_add_new(&new_hash, key, value); + } else { + zend_hash_next_index_insert_new(&new_hash, value); + } + } ZEND_HASH_FOREACH_END(); + } else { + uint32_t old_idx; + uint32_t new_idx = 0; + uint32_t iter_pos = zend_hash_iterators_lower_pos(Z_ARRVAL_P(stack), 0); + + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) { + if (key) { + zend_hash_add_new(&new_hash, key, value); + } else { + zend_hash_next_index_insert_new(&new_hash, value); + } + old_idx = (Bucket*)value - Z_ARRVAL_P(stack)->arData; + if (old_idx == iter_pos) { + zend_hash_iterators_update(Z_ARRVAL_P(stack), old_idx, new_idx); + iter_pos = zend_hash_iterators_lower_pos(Z_ARRVAL_P(stack), iter_pos + 1); + } + new_idx++; + } ZEND_HASH_FOREACH_END(); + } + + + Z_ARRVAL_P(stack)->u.v.nIteratorsCount = 0; + Z_ARRVAL_P(stack)->pDestructor = NULL; + zend_hash_destroy(Z_ARRVAL_P(stack)); + + Z_ARRVAL_P(stack)->u.v.flags = new_hash.u.v.flags; + Z_ARRVAL_P(stack)->nTableSize = new_hash.nTableSize; + Z_ARRVAL_P(stack)->nTableMask = new_hash.nTableMask; + Z_ARRVAL_P(stack)->nNumUsed = new_hash.nNumUsed; + Z_ARRVAL_P(stack)->nNumOfElements = new_hash.nNumOfElements; + Z_ARRVAL_P(stack)->nNextFreeElement = new_hash.nNextFreeElement; + Z_ARRVAL_P(stack)->arData = new_hash.arData; + Z_ARRVAL_P(stack)->pDestructor = new_hash.pDestructor; + + zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack)); + + return zend_hash_num_elements(Z_ARRVAL_P(stack)); +} +// /* }}} */ + + + + + #ifdef COMPILE_DL_SKYWALKING #ifdef ZTS ZEND_TSRMLS_CACHE_DEFINE() diff --git a/sky-php7ext/skywalking.php b/sky-php7ext/skywalking.php index cdf8f55472d8111ed8b924f333b1c035ad43244f..e0dffe0f718bf201580bebd60d12cdd424db721c 100644 --- a/sky-php7ext/skywalking.php +++ b/sky-php7ext/skywalking.php @@ -1,4 +1,47 @@ fwrite("124124"); + + + + $file = new SplFileObject('appid.pid'); +$aa = $file->current(); + +var_dump($aa); +exit; +function getfiles($path){ + foreach(scandir($path) as $afile) + { + if($afile=='.'||$afile=='..') continue; + if(is_file($path.'/'.$afile)){ + + echo $afile. "\n"; + } + } +} //简单的demo,列出当前目录下所有的文件 +getfiles(__DIR__); + +exit; +var_dump(base_convert(uniqid(), 16, 10)); +getMillisecond(); +function getMillisecond() + { + list($t1, $t2) = explode(' ', microtime()); + /*$t3 = $t1 * 100000000; + var_dump($t2, substr($t2, -6)); + $aa = (float)($t3 . substr($t2, -6)); + var_dump( (float)($t3 . substr($t2, -6))); + var_dump( json_encode(array("aaa"=> $aa))); + exit;*/ + $millisecond = (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 10000); + var_dump( json_encode(array("aaa"=> $millisecond))); + var_dump( $millisecond); + return $millisecond; + } + exit; +var_dump(json_encode(["applicationCode"=>"mapi"]));exit; +exit; $br = (php_sapi_name() == "cli")? "":"
"; if(!extension_loaded('skywalking')) {