未验证 提交 a497824e 编写于 作者: 何延龙 提交者: GitHub

Added memcache collection and skywalking 8.0 support

Added memcache collection and skywalking 8.0 support
上级 ccb58445
......@@ -9,10 +9,9 @@ SkyAPM PHP
## Documents
* [Documents in English](docs/README.md)
* [中文文档](docs/README_ZH.md)
## Docker image
Go to Docker hub -> [SkyAPM PHP](https://hub.docker.com/r/skyapm/skywalking-php)
Go to Docker hub -> [https://hub.docker.com/r/skyapm/skywalking-php](https://hub.docker.com/r/skyapm/skywalking-php)
```shell script
docker run -d -e SW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800 skywalking-php
```
......@@ -34,6 +33,7 @@ Host in Beijing. Go to [demo](http://106.75.237.45:8080/).
1. GRPC Client ([GRPC](https://github.com/grpc/grpc-php))
1. Predis Client ([Predis](https://packagist.org/packages/predis/predis))
1. Redis Extension ([Redis Extension](https://github.com/phpredis/phpredis))
1. Memcache Extension
## Contact Us
* Submit an [issue](https://github.com/SkyAPM/SkyAPM-php-sdk/issues)
......
.idea
\ No newline at end of file
# PHP SkyWalking Class: SkyWalking PHP client
---
- [Installation](#installation)
- [Requirements](#requirements)
- [Quick Start and Examples](#quick-start-and-examples)
---
### Installation
To install PHP SkyWalking Class, simply:
### 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
# 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
<?php
/**
* Class SkyWalking
* 需要 设置 LOG_PATH 常量 默认会放到/tmp/目录下
* 需要设置registerUrl 注册apm项 默认 appinfo.mservice.m.api:8080
*
* @package SkyWalking
*/
class SkyWalking
{
/**
* 当前类对象单列
* @var new self
*/
private static $_instance = null;
/**
* 当前应用系统名称
* @var $_appCode
*/
private static $_appCode = null;
/**
* SkyWalking 包含的头信息
* @var array
*/
private $_swHeaderInfo = array();
/**
* 唯一的事务编号
* @var
*/
private $_traceId;
private $_distributedTraceIds;
/**
* span节点的集合 数组
* 接口的 ss 列
* @var array
*/
private $_spansNodeData = array();
/**
* 总节点数据
* @var array
*/
private $_allNodeData = array();
/**
* 总段节点数据
*/
private $_allSegment = array();
/**
* 父节点数据
* @var array
*/
private $_fatherNodeData = array();
/**
* 单个span节点数据
* @var array
*/
private $_spanNodeData = array();
/**
* 第一个span节点数据
* @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
*/
private $_samplingRate = null;
private $_swHeaderText = null;
/**
* 本次进程是否采样
*/
private $_isSampling = null;
/**
* 关闭所有功能
*/
private $_isClose = 0;
/**
* 定义替换简单字符常量
*/
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 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 SPAN_TYPE_VALUE = 'tv';
const SPAN_LAYER_VALUE = "lv";
const FATHER_SPAN_ID = 'ps'; //父节点传过来的SpanId
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,
);
/**
* 全部段节点结构
*
* @var array
*/
private static $_allSegmentStruct = array
(
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节点数据集合
);
/**
* 父节点数据结构
* 数据格式
* @var array
*/
private static $_fatherNodesStruct = array(
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节点结构
* 数据格式
* @var array
*/
private static $_spanNodeDataStruct = array(
self::SPAN_ID => '',//SpanId
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 的日志
);
/**
* 进行单例处理
* @param $appCode
* @return SkyWalking
*/
public static function getInstance($appCode = '')
{
if (!(self::$_instance instanceof self)) {
self::$_instance = new self($appCode);
}
return self::$_instance;
}
private function __construct($appCode)
{
self::$_appCode = $appCode;
$this->_init();
}
/**
* 初始化节点信息
* TRACEID TraceId
* STARTTIME 总开始时间
* FATHER_NODE_DATA 父节点数据
* APP_CODE App Code
* DISTRIBUTED_TRACEIDS DistributedTraceIds
*/
private function _init()
{
if (empty(self::$_appCode)) {
throw new Exception("Error : Must set appCode");
}
if(!$this->appInitRegister()){
return ;
}
//注册一个结束函数
register_shutdown_function(array($this, "__finishAll"));
//对节点数据进行结构初始化
$this->_allNodeData = self::$_allNodesStruct;
//对段节点进行初始化
$this->_allSegment = self::$_allSegmentStruct;
/*
* 接收头信息 并对 _swHeaderInfo 进行赋值
* _swHeaderInfo 保存父节点
*/
$this->receiveSWHeaderFromCaller();
//总结阶段的链路全局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节点初始操作
* 当前页
*/
$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::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的curl信息的生产开始流程
* 请求curl前的span的生产
*
* @param string $peerHost 目标地址 生成SWTraceContext header使用
* @param array $headers CURL headers 数组内容
* @throws Exception
*/
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::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, "sw3: " . $_SWTraceHeader['SWTraceContext']);
}
/**
* @param resource $curl
* @throws Exception
*/
public function endSpanOfCurl($curl)
{
//此次是否采样
if (!$this->isSampling() || $this->_isClose) {
return;
}
if (empty($this->_spanNodeData[self::STARTTIME])) {
throw new Exception("Need setting start time");
}
if (!is_resource($curl) || strtolower(get_resource_type($curl)) != 'curl') {
throw new Exception("Need setting curl Object");
}
$curlInfo = curl_getinfo($curl);
$this->_spanNodeData[self::ENDTIME] = $this->getMillisecond();
//$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;
//获取当前服务端口号
if ($curlInfo['http_code'] != 200) {
$this->_spanNodeData[self::IS_ERROR] = true;
}
$this->_spanNodeData[self::TAGS][] = array('k'=>'url','v'=>$curlInfo['url']);
$this->setSpanNodeSData($this->_spanNodeData);
}
/**
* 生产最终结果 如果有 完成的回调处理并调用回调处理函数
* 已经被注册成结束函数自动调用
* @return string json
*/
public function __finishAll()
{
//此次是否采样
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();
array_unshift($this->_spansNodeData, $this->_spanFirstNodeData);
$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;
}
/**
* 设置 要写日志的路径
* @param $logPath
* @return $this
*/
public function setLogPath($logPath)
{
$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
* @return $this
*/
public function setSamplingRate($percent)
{
if ($percent >= 100) {
$percent = 100;
}
$this->_samplingRate = $percent;
return $this;
}
public function closeSampling(){
$this->_isSampling = false;
return $this;
}
/**
* 本次进程是否采样
* 若接收到header信息,则从header信息中继承采样率设置
* 若没有接收到header信息,并且也没有设置采样率,则为默认为 100%
* @return bool
*/
private function isSampling()
{
//判断没有计算过采样率
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;
}
/**
* 写日志
* @param $text
* @throws Exception
*/
private function writeLog($text)
{
if (!empty($this->_logPath)) {
$logPath = rtrim($this->_logPath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
} else {
$logPath = DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR;
}
$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($isArray = false)
{
//沿用父节点的TraceId ; 本节点生成的全链路系统唯一的事务编号。
if (!empty($this->_swHeaderInfo)) {
$this->_traceId = $this->_swHeaderInfo['TraceId'];
}
if (empty($this->_traceId)) {
$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();
}
/**
* 沿用父节点的DistributedTraceIds,如果没有父节点则再创建一个TraceId当做DistributedTraceIds,Trace.毫秒时间戳.UUID后7位的哈希码.当前进程号PID.当前线程ID.当前线程
* @return mixed|string
*/
private function _generateDistributedTraceIds()
{
if (!empty($this->_swHeaderInfo)) {
return $this->_swHeaderInfo['DistributedTraceIds'];
}
if (empty($this->_distributedTraceIds)) {
$this->_distributedTraceIds = $this->makeTraceId();
}
return $this->_distributedTraceIds;
}
/**
* 当前机器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)) {
if (isset($_SERVER['SERVER_ADDR'])) {
$ip = $_SERVER['SERVER_ADDR'];
} else {
$ip = $_SERVER['LOCAL_ADDR'];
}
} else {
$ip = getenv('SERVER_ADDR');
}
return $ip;
}
private function makeTraceId()
{
//生产唯一码毫秒时间戳.uuid.当前进程号PID.当前线程ID.当前线程生成的流水号.ip
$makeTraceIdArray = $this->_getIdParts();
return implode('.', $makeTraceIdArray);
}
private function getIp()
{
if (!empty($_SERVER['HTTP_DD_REAL_IP'])) {
$ip = $_SERVER['HTTP_DD_REAL_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} elseif (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
if (strpos($ip, ',') > 0) {
$ips = explode(',', $ip);
$ip = $ips[0];
}
return $ip;
}
/**
* 获取当前的url
* @return string
*/
private function getPageUrlAndPeer(){
$pageURL = 'http';
if (isset($_SERVER["HTTPS"]) && ($_SERVER["HTTPS"] == "on")) {
$pageURL .= "s";
}
$pageURL .= "://";
$peer = $_SERVER["HTTP_HOST"];
$pageURL .= $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
return array($pageURL, $peer);
}
/**
* 生成 SpanId
* 用于此次调用的区块标示
*/
private function _generateSpanId()
{
return $this->_spanID++;
}
private function getMillisecond()
{
list($t1, $t2) = explode(' ', microtime());
$millisecond = (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000);
return $millisecond;
}
/**
* 获取接收到 SWTraceContext 的 header
*/
private function receiveSWHeaderFromCaller()
{
if (!empty($_SERVER['HTTP_SWTRACECONTEXT'])) {
$this->_swHeaderText = $_SERVER['HTTP_SWTRACECONTEXT'];
list(
$this->_swHeaderInfo['traceId'],
$this->_swHeaderInfo['SpanId'],
$this->_swHeaderInfo['ParentAppInstanceid'],
$this->_swHeaderInfo['EntryAppInstanceid'],
$this->_swHeaderInfo['PeerHost'],
$this->_swHeaderInfo['EntryAppnameOperationId'],
$this->_swHeaderInfo['ParentAppnameOperationId'],
$this->_swHeaderInfo['DistributedTraceIds']
) = explode('|', $this->_swHeaderText);
}
return $this->_swHeaderInfo;
}
/**
* 生成调用接口的 header
* @param string $peerHost
* @return array
* @throws \Exception
*/
private function _buildSWHeaderValue($peerHost)
{
$_SWHeader = array();
$_SWHeader['traceId'] = $this->_generateTraceId();
$_SWHeader['SpanId'] = $this->_generateSpanId();
$_SWHeader['ParentAppInstanceid'] = $this->_parentAppInstanceid();
$_SWHeader['EntryAppInstanceid'] = $this->_entryAppInstanceid();
$_SWHeader['PeerHost'] = '#' . $peerHost;
$_SWHeader['EntryAppnameOperationId'] = $this->_entryAppnameOperationId();
$_SWHeader['ParentAppnameOperationId'] = $this->_parentAppnameOperationId();
$_SWHeader['DistributedTraceIds'] = $this->_generateDistributedTraceIds();
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) {
}
}
}
<?php
/**
* 其他项目调用此项目会传递类似 HEADER 信息
* $_SERVER['HTTP_SWTRACECONTEXT'] = 'Segment1504173645811.59a7de4dc618f.14768.0.0.127.0.0.1|59a7de4dc61c5|api|baidu.com|Segment1504173645811.59a7de4dc61b0.14768.0.0.127.0.0.1|1';
*
*/
include_once ("./SkyWalking.php");
SkyWalking::getInstance("mapi");
/**
* 定义日志目录,目前传递数据使用log方式
* 设置log写入路径的方法:
*/
define('LOG_PATH', dirname(__FILE__) . DIRECTORY_SEPARATOR . 'log');
SkyWalking::getInstance("api")->setLogPath(LOG_PATH)->setSamplingRate(5);
//发起B请求
sendA();
//发起B请求
sendB();
//发起B请求
sendC();
function sendA(){
/** start 应用本身的业务代码 **/
$headers = array(
"Content-type: text/xml",
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Cache-Control: no-cache",
"Pragma: no-cache",
);
/** end 应用本身的业务代码 **/
SkyWalking::getInstance()->startSpanOfCurl("api.com", $headers);
//var_dump($headers);
/** start 应用本身的业务代码 **/
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://www.api.com/');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl,CURLOPT_HTTPHEADER,$headers);
curl_setopt($curl, CURLOPT_HEADER, 0);
$result = curl_exec($curl);
$errno = curl_errno($curl);
$error = curl_error($curl);
/** end 应用本身的业务代码 **/
SkyWalking::getInstance()->endSpanOfcurl($curl);
/** start 应用本身的业务代码 **/
curl_close($curl);
/** end 应用本身的业务代码 **/
}
function sendB(){
/** start 应用本身的业务代码 **/
$headers = array(
"Content-type: text/xml",
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Cache-Control: no-cache",
"Pragma: no-cache",
);
/** end 应用本身的业务代码 **/
SkyWalking::getInstance()->startSpanOfCurl("api.com", $headers);
//var_dump($headers);
/** start 应用本身的业务代码 **/
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://www.api.com/');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl,CURLOPT_HTTPHEADER,$headers);
curl_setopt($curl, CURLOPT_HEADER, 0);
$result = curl_exec($curl);
$errno = curl_errno($curl);
$error = curl_error($curl);
/** end 应用本身的业务代码 **/
SkyWalking::getInstance()->endSpanOfcurl($curl);
/** start 应用本身的业务代码 **/
curl_close($curl);
/** end 应用本身的业务代码 **/
}
function sendC(){
/** start 应用本身的业务代码 **/
$headers = array(
"Content-type: text/xml",
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Cache-Control: no-cache",
"Pragma: no-cache",
);
/** end 应用本身的业务代码 **/
SkyWalking::getInstance()->startSpanOfCurl("api.com", $headers);
//var_dump($headers);
/** start 应用本身的业务代码 **/
/** start 应用本身的业务代码 **/
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://www.api.com/');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl,CURLOPT_HTTPHEADER,$headers);
curl_setopt($curl, CURLOPT_HEADER, 0);
$result = curl_exec($curl);
$errno = curl_errno($curl);
$error = curl_error($curl);
/** end 应用本身的业务代码 **/
SkyWalking::getInstance()->endSpanOfcurl($curl);
/** start 应用本身的业务代码 **/
curl_close($curl);
/** end 应用本身的业务代码 **/
}
\ No newline at end of file
......@@ -20,7 +20,7 @@ func main() {
app := cli.NewApp()
app.Name = "sky_php_agent"
app.Usage = "the skywalking trace sending agent"
app.Version = "3.2.8"
app.Version = "3.3.0"
app.Flags = []cli.Flag{
&cli.StringSliceFlag{Name: "grpc", Usage: "SkyWalking collector address", Value: cli.NewStringSlice("127.0.0.1:11800")},
&cli.StringFlag{Name: "socket", Usage: "Pipeline for communicating with PHP", Value: "/tmp/sky-agent.sock"},
......
......@@ -2,4 +2,4 @@
* Quick Start
* [Quick start](quick-start.md)
* [Install agent](install-agent.md)
* [Install](install.md)
文档
=====
* [更改记录](./zh/change-log.md)
* [安装php扩展](./zh/install-sdk.md)
* [启动agent](./zh/start-agent.md)
* [常见问题](./zh/qa.md)
\ No newline at end of file
Tips: It is recommended that you use SkyWalking and use nginx as load balancing
Tips: It is recommended to use nginx as the load balancer of SkyWalking-oap-server
# Install SkyWalking PHP Agent
......@@ -12,15 +12,15 @@ When building directly from Git sources or after custom modifications you might
## PHP extension + Agent
The collect data from your instance you need both the PHP extension, and the agent.
No pre built binaries or PHP extension are availble at the moment, so you need to
build them from source.
build them from a source.
You can run the following commands to install the SkyWalking PHP Agent.
## Install PHP Extension
## Install PHP Extension
```shell script
curl -Lo v3.2.8.tar.gz https://github.com/SkyAPM/SkyAPM-php-sdk/archive/v3.2.8.tar.gz
tar zxvf v3.2.8.tar.gz
cd SkyAPM-php-sdk-3.2.8
curl -Lo v3.3.0.tar.gz https://github.com/SkyAPM/SkyAPM-php-sdk/archive/v3.3.0.tar.gz
tar zxvf v3.3.0.tar.gz
cd SkyAPM-php-sdk-3.3.0
phpize && ./configure && make && make install
```
......@@ -29,7 +29,7 @@ phpize && ./configure && make && make install
For installing the sky-php-agent, you first need to build it:
```shell script
cd SkyAPM-php-sdk-3.2.8
cd SkyAPM-php-sdk-3.3.0
go build -o sky-php-agent cmd/main.go
chmod +x sky-php-agent
cp sky-php-agent /usr/local/bin
......@@ -37,7 +37,7 @@ cp sky-php-agent /usr/local/bin
## How to use
### Add skywalking config to php.ini and restart php-fpm
### Add SkyWalking config to php.ini and restart php-fpm
```shell script
; Loading extensions in PHP
......@@ -47,119 +47,31 @@ extension=skywalking.so
skywalking.enable = 1
; Set skyWalking collector version (5 or 6 or 7 or 8)
skywalking.version = 6
skywalking.version = 8
; Set app code e.g. MyProjectName
skywalking.app_code = MyProjectName
; sock file path(default /tmp/sky-agent.sock)
; sock file path default /tmp/sky-agent.sock
; Warning *[systemd] please disable PrivateTmp feature*
; Warning *Make sure PHP has read and write permissions on the socks file*
skywalking.sock_path=/tmp/sky-agent.sock
```
## Select startup script and log output method
## If you use CentOS 7 Use the startup script below to You need to change the corresponding address, version
## sky-php-agent `systemd` example
```shell script
[Unit]
Description=The Sw-Php-Agent Process Manager
Description=The SkyWalking PHP-Agent Process Manager
After=syslog.target network.target
[Service]
Type=simple
#Modify the corresponding directory and address here
ExecStart=/usr/local/bin/sky-php-agent-linux-X64 --grpc=127.0.0.1:11800 --sky-version=7 --socket=/tmp/sky-agent.sock
# Modify the corresponding directory and address here
ExecStart=/usr/local/bin/sky-php-agent --grpc=127.0.0.1:11800 --sky-version=8 --socket=/tmp/sky-agent.sock
ExecStop=/bin/kill -SIGINT $MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target
```
## If you use CentOS6 Log management with lograted
## This is Start script You need to change the address, version and Copy and run it with root
```shell script
echo "
#/bin/bash
start(){
[ -f /tmp/php-agent.pid ]&&echo "Alredy running"&&exit 1
/usr/local/bin/sky-php-agent-linux-X64 --grpc=127.0.0.1:11800 --sky-version=7 --socket=/tmp/sky-agent.sock 1>>/var/log/phpagent/php-agent.log 2>>/var/log/phpagent/php-agent-error.log &
if [ $? -eq 0 ];then
echo $! >/tmp/php-agent.pid
echo "sky-php-agent startup!!!"
fi
}
stop(){
kill -9 `cat /tmp/php-agent.pid`
rm -f /tmp/php-agent.pid
[[ $? == 0 ]]&&echo "sky-php-agent stop!!!"
}
# add the restart method
case $1 in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
echo "USAGE: $0 {start |stop |restart }"
;;
esac
exit 0 " > /etc/init.d/php-agent
```
## This is Log management script,Copy and run it with root
```shell script
mkdir /var/log/phpagent/
echo "
/var/log/phpagent/*.log {
rotate 10
daily
dateext
nocompress
missingok
notifempty
create 0644 root root
postrotate
/etc/init.d/php-agent restart
endscript
}" >/etc/logrotate.d/phpagent
```
### Agent parameter description
```shell script
# View help information
./sky-php-agent -h
# Specify grpc address
/usr/local/bin/sky-php-agent --grpc 127.0.0.1:11800
# Specify the socket file. The path is the path in the php.ini configuration
/usr/local/bin/sky-php-agent --socket=/tmp/sky-agent.sock
# Specify the version of skywalking
/usr/local/bin/sky-php-agent --sky-version=7
```
### ⚠️⚠️⚠️ Warning *Make sure PHP has read and write permissions on the socks file*
# todo
# Get started quickly with docker
See [Install agent](install-agent.md)
\ No newline at end of file
See [docker-compose.yml](../docker-compose.yml)
See [Dockerfile](../Dockerfile)
# 20191001
## Agent 修改
1. 修改文件权限为0777
1. 执行`sky-php-agent -h` 查看可用参数
# 20190722
## SkyWalking 扩展修改
1. 支持对mysqli扩展的支持(目前暂时仅支持`mysqli::query()`)
# 20190719
## Agent 修改
1. agent创建的文件权限修改为0666, 文件的类型修改为sock类型。修复php与sock文件进行通信时提示"Permission Deny"的问题
2. agent的参数接收方式修改, 执行`sky-php-agent -h` 查看可用参数
3. agent支持在参数中指定sock文件的路径
## SkyWalking 扩展修改
1. 新增 skywalking_get_trace_info():array 方法,获取trace数据,以方便业务日志获取当前请求trace信息。
2. 删除无用的skywalking.log_path及skywalking.grpc配置项
3. 新增 skywalking.sock_path 配置项,支持自定义sock文件的路径
# 环境
PHP7+
# 安装
## 安装PHP的SkyWalking扩展(Ubuntu环境)
1.安装php-dev (具体的PHP版本以你的环境为准,必须php7+)
```shell
sudo apt install php7.2-dev
```
2.安装curl开发包
```shell
sudo apt install curl-dev
```
3.git clone 源码
```shell
git clone https://github.com/SkyAPM/SkyAPM-php-sdk.git /path/to/SkyAPM-php-sdk
```
4.编译安装SkyAPM-php-sdk
```shell
cd /path/to/SkyAPM-php-sdk
phpize
./configure
make
sudo make install
```
5.新建php的skywalking扩展配置文件,写入配置
```shell
; 扩展so
extension=skywalking.so
; 是否启用:0 关闭;1 启用 (默认值为0)
skywalking.enable=1
; skywalking的版本:5或者6(默认值为6)
skywalking.version=6
; app_code代码,不要含特殊字符,请使用数字、字母、下换线。(默认为:hello_skywalking)
skywalking.app_code=hello_skywalking
; sock文件路径(默认值为/var/run/sky-agent.sock)
skywalking.sock_path=/var/run/sky-agent.sock
```
6.重启php-fpm服务
```shell
sudo service php-fpm restart
```
7.查看skywalking扩展是否成功加载
```shell
php -m | grep skywalking
```
查看具体配置,请使用`php -i`或者`phpinfo()`函数
# 常见问题
-----
1. linux下php不能读取/tmp文件夹下文件,即php无法与/tmp目录下的sock文件进行通信。
该问题一般是由`systemd`服务的`PrivateTmp`属性配置导致的。
`systemd`中服务的配置文件都在目录`/lib/systemd/system/`中:
* 检查SELinux配置,可尝试关闭SELinux
* `apache`的配置文件为`apache2.service`
* `php-fpm`的配置文件为`php-fpm.service` (可能会存在版本号,例如`php7.2-fpm.service`)
修改`PrivateTmp`属性的取值为`false`, 再执行`sudo systemctl daemon-reload`, 最后再重启`apache`或者`php-fpm`
1. 对于已经安装并启用了`SkyWalking`扩展的PHP环境的主机,所发送的trace信息在哪里?
* 如果`skywalking.version=5`, 则`http`请求的`header`中会加入一个名为`SW3`的数据。PHP可使用`$_SERVER['HTTP_SW3']`获取。[协议文档](https://github.com/apache/skywalking/blob/master/docs/en/protocols/Skywalking-Cross-Process-Propagation-Headers-Protocol-v1.md)
* 如果`skywalking.version=6`, 则`http`请求的`header`中会加入一个名为`SW6`的数据。PHP可使用`$_SERVER['HTTP_SW6']`获取。[协议文档](https://github.com/apache/skywalking/blob/master/docs/en/protocols/Skywalking-Cross-Process-Propagation-Headers-Protocol-v2.md)
* SW6值格式为:`1-{distributedTraceIdEncode}-{traceSegmentIdEncode}-{span_id}-{application_instance}-{entryApplicationInstance}-{peerHostEncode}-{entryEndpointNameEncode}-{parentEndpointNameEncode}`, Encode算法为base64_encode()。示例取值为:`1-OTQuMjIyMzUuMTU2MjkxMDg1MzAwMDM=-OTQuMjIyMzUuMTU2MjkxMDg1MzAwMDM=-1-94-94-IwE6NDQz-Iy9pbmRleC5waHA/ZGRkZGRkZA==-IwE=`
* 值中`distributedTraceId`即下方的`globalTraceIds[0]`的取值
1. 会传递trace信息的请求类型有哪些?
* php curl扩展发出的请求
* php PDO扩展发出的请求
* php mysqli扩展发出的请求
* php yar扩展(client)发出的请求
* php [grpc/grpc](https://github.com/grpc/grpc-php) 发出的请求
* php redis扩展发出的请求
* php predis库发出的请求
1. skywalking_get_trace_info()函数的返回值格式?
* 返回值为数组。如果扩展加载但是未启用(`skywalking.enable=0`), 则返回空数组
```php
# skywalking_get_trace_info 返回值格式如下:
[
'application_instance' => 94,
'pid' => 22230,
'application_id' => 29,
'version' => 6,
'segment' => [
'traceSegmentId' => '94.22412.15629106130002',
'isSizeLimited' => 0,
'spans' => [
[
'tags' => [
'url' => '/index.php?id=123'
],
'spanId' => 0,
'parentSpanId' => -1,
'startTime' => 1562910613896,
'operationName' => '/index.php',
'peer' => '127.0.0.1:80',
'spanType' => 0,
'spanLayer' => 3,
'componentId' => 2,
'refs' => [
[
'type' => 0,
'parentTraceSegmentId' => '94.22412.15629106130002',
'parentSpanId' => 1,
'parentApplicationInstanceId' => 94,
'networkAddress' => ':443',
'entryApplicationInstanceId' => 94,
'entryServiceName' => 'index.php?to=123',
'parentServiceName' => '',
],
],
],
],
],
'globalTraceIds' => [
'94.22235.15629108530003',
],
]
```
1. mysqli有过程式风格和对象式风格,上报的数据有何不同?
* 目前扩展仅监控mysqli_query()、mysqli::query()方法, 并记录对应执行的sql, 在上报到oapServer的时候,统一按照mysqli->query()的格式进行上报
\ No newline at end of file
# 启动agent
1.选择你的操作系统对应的agent应用程序
darwin指MacOS操作系统, linux指Linux操作系统
x64/x86分别指64位操作系统/32位操作系统
```
sky-php-agent-darwin-x64
sky-php-agent-darwin-x86
sky-php-agent-linux-x64
sky-php-agent-linux-x86
sky-php-agent-linux-arm64
sky-php-agent-linux-arm86
```
2.启动agent(以 Ubuntu x64 平台示例)
```shell
# 添加可执行权限
sudo chmod +x ./sky-php-agent-linux-x64
# 启动
./sky-php-agent-linux-x64 127.0.0.1:11800 /var/run/sky-agent.sock
```
3.agent 参数说明
* 第一个参数为SkyWalking服务端的GRPC地址
* 第二个参数为sock文件的绝对路径,必须与php中skywalking.sock_path的路径一致。默认值为:`/var/run/sky-agent.sock`
* `-h` 可查看帮助信息
......@@ -26,7 +26,7 @@
</stability>
<license uri="http://www.apache.org/licenses/LICENSE-2.0.html">Apache2.0</license>
<notes>
Fix the mistake of field entryOperationName in sw6 header.
{{notes}}
</notes>
<contents>
<dir name="/">
......@@ -47,6 +47,19 @@
<extsrcrelease />
<changelog>
{{release}}
<release>
<version>
<release>3.3.0</release>
<api>3.3.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<notes>
Added memcache collection and skywalking 8.0 support
</notes>
</release>
<release>
<version>
<release>3.2.8</release>
......@@ -100,4 +113,4 @@
</notes>
</release>
</changelog>
</package>
\ No newline at end of file
</package>
......@@ -15,10 +15,10 @@
<email>yanlong@php.net</email>
<active>yes</active>
</lead>
<date>2020-03-23</date>
<date>2020-05-12</date>
<version>
<release>3.2.8</release>
<api>3.2.8</api>
<release>3.3.0</release>
<api>3.3.0</api>
</version>
<stability>
<release>stable</release>
......@@ -26,7 +26,7 @@
</stability>
<license uri="http://www.apache.org/licenses/LICENSE-2.0.html">Apache2.0</license>
<notes>
Fix the mistake of field entryOperationName in sw6 header.
Added memcache collection and skywalking 8.0 support
</notes>
<contents>
<dir name="/">
......@@ -35,52 +35,19 @@
<file role="doc" name="EXPERIMENTAL" />
<file role="doc" name="LICENSE" />
<file role="doc" name="README.md" />
<file role="src" name="agent/.gitignore" />
<file role="src" name="agent/cmd/main.go" />
<file role="src" name="agent/logger/log.go" />
<file role="src" name="agent/pb/agent/ApplicationRegisterService.pb.go" />
<file role="src" name="agent/pb/agent/CLR.pb.go" />
<file role="src" name="agent/pb/agent/DiscoveryService.pb.go" />
<file role="src" name="agent/pb/agent/Downstream.pb.go" />
<file role="src" name="agent/pb/agent/JVM.pb.go" />
<file role="src" name="agent/pb/agent/JVMMetricsService.pb.go" />
<file role="src" name="agent/pb/agent/KeyWithIntegerValue.pb.go" />
<file role="src" name="agent/pb/agent/KeyWithStringValue.pb.go" />
<file role="src" name="agent/pb/agent/NetworkAddressRegisterService.pb.go" />
<file role="src" name="agent/pb/agent/TraceSegmentService.pb.go" />
<file role="src" name="agent/pb/agent/trace-common.pb.go" />
<file role="src" name="agent/pb/agent2/CLRMetric.pb.go" />
<file role="src" name="agent/pb/agent2/JVMMetric.pb.go" />
<file role="src" name="agent/pb/agent2/trace.pb.go" />
<file role="src" name="agent/pb/common/common.pb.go" />
<file role="src" name="agent/pb/register2/InstancePing.pb.go" />
<file role="src" name="agent/pb/register2/Register.pb.go" />
<file role="src" name="agent/pb/servicemesh/service-mesh.pb.go" />
<file role="src" name="agent/service/agent.go" />
<file role="src" name="agent/service/conn.go" />
<file role="src" name="agent/service/heartbeat.go" />
<file role="src" name="agent/service/register.go" />
<file role="src" name="agent/service/trace.go" />
<file role="src" name="b64.h" />
<file role="src" name="bak/.gitignore" />
<file role="doc" name="bak/README.md" />
<file role="doc" name="bak/README_ZH.md" />
<file role="src" name="bak/SkyWalking.php" />
<file role="src" name="bak/demo.php" />
<file role="src" name="build-sky-php-agent.sh" />
<file role="src" name="cmd/main.go" />
<file role="src" name="components.h" />
<file role="src" name="config.m4" />
<file role="src" name="config.w32" />
<file role="src" name="decode.c" />
<file role="src" name="docker-compose.yml" />
<file role="doc" name="docs/README.md" />
<file role="doc" name="docs/README_ZH.md" />
<file role="doc" name="docs/install-agent.md" />
<file role="doc" name="docs/install.md" />
<file role="doc" name="docs/quick-start.md" />
<file role="doc" name="docs/zh/change-log.md" />
<file role="doc" name="docs/zh/install-sdk.md" />
<file role="doc" name="docs/zh/qa.md" />
<file role="doc" name="docs/zh/start-agent.md" />
<file role="src" name="encode.c" />
<file role="src" name="gen-proto.sh" />
<file role="src" name="go.mod" />
<file role="src" name="go.sum" />
<file role="src" name="nginx.conf" />
......@@ -88,26 +55,63 @@
<file role="src" name="pecl-package.php" />
<file role="src" name="php.ini" />
<file role="src" name="php_skywalking.h" />
<file role="doc" name="proto/README.md" />
<file role="src" name="proto/common/CLR.proto" />
<file role="src" name="proto/common/JVM.proto" />
<file role="src" name="proto/common/common.proto" />
<file role="src" name="proto/common/trace-common.proto" />
<file role="src" name="proto/language-agent-v2/CLRMetric.proto" />
<file role="src" name="proto/language-agent-v2/JVMMetric.proto" />
<file role="src" name="proto/language-agent-v2/trace.proto" />
<file role="src" name="proto/language-agent/ApplicationRegisterService.proto" />
<file role="src" name="proto/language-agent/DiscoveryService.proto" />
<file role="src" name="proto/language-agent/Downstream.proto" />
<file role="src" name="proto/language-agent/JVMMetricsService.proto" />
<file role="src" name="proto/language-agent/KeyWithIntegerValue.proto" />
<file role="src" name="proto/language-agent/KeyWithStringValue.proto" />
<file role="src" name="proto/language-agent/NetworkAddressRegisterService.proto" />
<file role="src" name="proto/language-agent/TraceSegmentService.proto" />
<file role="src" name="proto/register/InstancePing.proto" />
<file role="src" name="proto/register/Register.proto" />
<file role="src" name="proto/service-mesh-probe/istio/skywalking.config.pb.html" />
<file role="src" name="proto/service-mesh-probe/service-mesh.proto" />
<file role="src" name="reporter/logger/log.go" />
<file role="src" name="reporter/network/common/v1/common.pb.go" />
<file role="src" name="reporter/network/common/v2/common.pb.go" />
<file role="src" name="reporter/network/common/v3/Common.pb.go" />
<file role="src" name="reporter/network/language/agent/v1/ApplicationRegisterService.pb.go" />
<file role="src" name="reporter/network/language/agent/v1/CLR.pb.go" />
<file role="src" name="reporter/network/language/agent/v1/DiscoveryService.pb.go" />
<file role="src" name="reporter/network/language/agent/v1/Downstream.pb.go" />
<file role="src" name="reporter/network/language/agent/v1/JVM.pb.go" />
<file role="src" name="reporter/network/language/agent/v1/JVMMetricsService.pb.go" />
<file role="src" name="reporter/network/language/agent/v1/KeyWithIntegerValue.pb.go" />
<file role="src" name="reporter/network/language/agent/v1/KeyWithStringValue.pb.go" />
<file role="src" name="reporter/network/language/agent/v1/NetworkAddressRegisterService.pb.go" />
<file role="src" name="reporter/network/language/agent/v1/TraceSegmentService.pb.go" />
<file role="src" name="reporter/network/language/agent/v1/trace-common.pb.go" />
<file role="src" name="reporter/network/language/agent/v2/CLR.pb.go" />
<file role="src" name="reporter/network/language/agent/v2/CLRMetric.pb.go" />
<file role="src" name="reporter/network/language/agent/v2/JVM.pb.go" />
<file role="src" name="reporter/network/language/agent/v2/JVMMetric.pb.go" />
<file role="src" name="reporter/network/language/agent/v2/trace-common.pb.go" />
<file role="src" name="reporter/network/language/agent/v2/trace.pb.go" />
<file role="src" name="reporter/network/language/agent/v3/CLRMetric.pb.go" />
<file role="src" name="reporter/network/language/agent/v3/JVMMetric.pb.go" />
<file role="src" name="reporter/network/language/agent/v3/Tracing.pb.go" />
<file role="src" name="reporter/network/language/profile/v2/Profile.pb.go" />
<file role="src" name="reporter/network/language/profile/v3/Profile.pb.go" />
<file role="src" name="reporter/network/management/v3/Management.pb.go" />
<file role="src" name="reporter/network/register/v2/InstancePing.pb.go" />
<file role="src" name="reporter/network/register/v2/Register.pb.go" />
<file role="src" name="reporter/protocol/v1/common/CLR.proto" />
<file role="src" name="reporter/protocol/v1/common/JVM.proto" />
<file role="src" name="reporter/protocol/v1/common/common.proto" />
<file role="src" name="reporter/protocol/v1/common/trace-common.proto" />
<file role="src" name="reporter/protocol/v1/language-agent/ApplicationRegisterService.proto" />
<file role="src" name="reporter/protocol/v1/language-agent/DiscoveryService.proto" />
<file role="src" name="reporter/protocol/v1/language-agent/Downstream.proto" />
<file role="src" name="reporter/protocol/v1/language-agent/JVMMetricsService.proto" />
<file role="src" name="reporter/protocol/v1/language-agent/KeyWithIntegerValue.proto" />
<file role="src" name="reporter/protocol/v1/language-agent/KeyWithStringValue.proto" />
<file role="src" name="reporter/protocol/v1/language-agent/NetworkAddressRegisterService.proto" />
<file role="src" name="reporter/protocol/v1/language-agent/TraceSegmentService.proto" />
<file role="doc" name="reporter/protocol/v2/README.md" />
<file role="src" name="reporter/protocol/v2/common/CLR.proto" />
<file role="src" name="reporter/protocol/v2/common/JVM.proto" />
<file role="src" name="reporter/protocol/v2/common/common.proto" />
<file role="src" name="reporter/protocol/v2/common/trace-common.proto" />
<file role="src" name="reporter/protocol/v2/language-agent-v2/CLRMetric.proto" />
<file role="src" name="reporter/protocol/v2/language-agent-v2/JVMMetric.proto" />
<file role="src" name="reporter/protocol/v2/language-agent-v2/trace.proto" />
<file role="src" name="reporter/protocol/v2/profile/Profile.proto" />
<file role="src" name="reporter/protocol/v2/register/InstancePing.proto" />
<file role="src" name="reporter/protocol/v2/register/Register.proto" />
<file role="src" name="reporter/service/agent.go" />
<file role="src" name="reporter/service/conn.go" />
<file role="src" name="reporter/service/heartbeat.go" />
<file role="src" name="reporter/service/register.go" />
<file role="src" name="reporter/service/trace.go" />
<file role="src" name="service.sh" />
<file role="src" name="skywalking.c" />
<file role="src" name="skywalking.php" />
......@@ -145,7 +149,6 @@
<file role="test" name="tests/skywalking.20171027.log" />
<file role="src" name="travis/route.sh" />
<file role="src" name="travis/simple-compile.sh" />
<file role="src" name="who-uses.jpg" />
</dir>
</contents>
......@@ -163,6 +166,19 @@
<extsrcrelease />
<changelog>
<release>
<version>
<release>3.3.0</release>
<api>3.3.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<notes>
Added memcache collection and skywalking 8.0 support
</notes>
</release>
<release>
<version>
<release>3.2.8</release>
......@@ -216,4 +232,4 @@
</notes>
</release>
</changelog>
</package>
\ No newline at end of file
</package>
......@@ -16,9 +16,13 @@ $header = file_get_contents("$root_dir/php_skywalking.h");
$header = preg_replace("/PHP_SKYWALKING_VERSION \"(\d.\d.\d)\"/i", 'PHP_SKYWALKING_VERSION "' . $version . '"', $header);
file_put_contents("$root_dir/php_skywalking.h", $header);
$agent = file_get_contents("$root_dir/agent/cmd/main.go");
$agent = file_get_contents("$root_dir/cmd/main.go");
$agent = preg_replace("/app.Version = \"(\d.\d.\d)\"/i", 'app.Version = "' . $version . '"', $agent);
file_put_contents("$root_dir/agent/cmd/main.go", $agent);
file_put_contents("$root_dir/cmd/main.go", $agent);
$insert = file_get_contents("$root_dir/docs/install.md");
$insert = preg_replace("/(\d.\d.\d)/i", $version, $insert);
file_put_contents("$root_dir/docs/install.md", $insert);
echo "version: $version\n";
......@@ -76,6 +80,7 @@ $template = str_replace("{{file_list}}", implode(" ", $file_list), $t
$template = str_replace("{{version}}", $version, $template);
$template = str_replace("{{date}}", date("Y-m-d"), $template);
$template = str_replace("{{release}}", "", $template);
$template = str_replace("{{notes}}", $desc, $template);
file_put_contents("package.xml", $template);
......@@ -11,5 +11,5 @@
extension=skywalking.so
skywalking.app_code = hello_skywalking
skywalking.enable = 1
skywalking.version = 6
skywalking.sock_path = /tmp/sky-agent.sock
\ No newline at end of file
skywalking.version = 8
skywalking.sock_path = /tmp/sky-agent.sock
......@@ -25,7 +25,7 @@ extern zend_module_entry skywalking_module_entry;
#define phpext_skywalking_ptr &skywalking_module_entry
#define SKY_DEBUG 0
#define PHP_SKYWALKING_VERSION "3.2.8" /* Replace with version number for your extension */
#define PHP_SKYWALKING_VERSION "3.3.0" /* Replace with version number for your extension */
#ifdef PHP_WIN32
# define PHP_SKYWALKING_API __declspec(dllexport)
......
......@@ -189,7 +189,11 @@ func (t *Agent) sub() {
go t.doRegister(register)
case trace := <-t.trace:
t.queueLock.Lock()
t.queue = append(t.queue, trace)
if len(t.queue) < 65535*2 {
t.queue = append(t.queue, trace)
} else {
log.Warnf("trace queue is fill.")
}
t.queueLock.Unlock()
}
}
......
[Unit]
Description=The SkyWalking PHP-Agent Process Manager
After=syslog.target network.target
[Service]
Type=simple
#Modify the corresponding directory and address here
ExecStart=/usr/local/bin/sky-php-agent --grpc=127.0.0.1:11800 --sky-version=7 --socket=/tmp/sky-agent.sock
ExecStop=/bin/kill -SIGINT $MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册