Add swoole support. (#19)
Co-authored-by: 何延龙 <hey.yanlong@gmail.com>
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index b649079..597408b 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -19,6 +19,7 @@
push:
branches:
- master
+ - debug
pull_request:
branches:
- "**"
diff --git a/README.md b/README.md
index da1c3a0..e0c59ae 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,14 @@
* [ ] [php-rdkafka](https://github.com/arnaud-lb/php-rdkafka)
* [ ] [predis](https://github.com/predis/predis)
+* Swoole Ecosystem
+ * [ ] [Coroutine\Http\Client](https://wiki.swoole.com/#/coroutine_client/http_client)
+ * [ ] [Coroutine\MySQL](https://wiki.swoole.com/#/coroutine_client/mysql)
+ * [ ] [Swoole\Coroutine\Http\Client](https://wiki.swoole.com/#/coroutine_client/http_client)
+ * [ ] [Coroutine\Redis](https://wiki.swoole.com/#/coroutine_client/redis)
+
+ *The components of the PHP-FPM ecosystem can also be used in Swoole.*
+
## Contact Us
* Mail list: **dev@skywalking.apache.org**. Mail to `dev-subscribe@skywalking.apache.org`, follow the reply to subscribe the mail list.
diff --git a/docs/en/setup/service-agent/php-agent/Supported-list.md b/docs/en/setup/service-agent/php-agent/Supported-list.md
index fafae02..0804886 100644
--- a/docs/en/setup/service-agent/php-agent/Supported-list.md
+++ b/docs/en/setup/service-agent/php-agent/Supported-list.md
@@ -5,6 +5,7 @@
## Supported SAPI
* PHP-FPM
+* CLI under [Swoole](https://www.swoole.com/)
## Support PHP extension
diff --git a/src/lib.rs b/src/lib.rs
index c08a17c..4ffa85a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -93,14 +93,13 @@
module.on_request_init(request::init);
module.on_request_shutdown(request::shutdown);
- // TODO Add swoole in future.
// The function is used by swoole plugin, to surround the callback of on
// request.
- // module.add_function(
- // "skywalking_hack_swoole_on_request_please_do_not_use",
- // request::skywalking_hack_swoole_on_request,
- // vec![],
- // );
+ module.add_function(
+ "skywalking_hack_swoole_on_request_please_do_not_use",
+ request::skywalking_hack_swoole_on_request,
+ vec![],
+ );
module
}
diff --git a/src/module.rs b/src/module.rs
index ea96f16..332e5a8 100644
--- a/src/module.rs
+++ b/src/module.rs
@@ -106,7 +106,6 @@
}
}
-#[allow(dead_code)]
fn get_module_registry() -> &'static ZArr {
unsafe { ZArr::from_ptr(&sys::module_registry) }
}
@@ -122,10 +121,9 @@
return true;
}
- // TODO Add swoole in future.
- // if sapi == b"cli" && get_module_registry().exists("swoole") {
- // return true;
- // }
+ if sapi == b"cli" && get_module_registry().exists("swoole") {
+ return true;
+ }
false
}
diff --git a/src/plugin/mod.rs b/src/plugin/mod.rs
index 1e8851d..cffafc9 100644
--- a/src/plugin/mod.rs
+++ b/src/plugin/mod.rs
@@ -25,9 +25,8 @@
vec![
Box::new(plugin_curl::CurlPlugin::default()),
Box::new(plugin_pdo::PdoPlugin::default()),
- // TODO Add swoole in future.
- // Box::new(plugin_swoole::SwooleServerPlugin::default()),
- // Box::new(plugin_swoole::SwooleHttpResponsePlugin::default()),
+ Box::new(plugin_swoole::SwooleServerPlugin::default()),
+ Box::new(plugin_swoole::SwooleHttpResponsePlugin::default()),
]
});
diff --git a/src/request.rs b/src/request.rs
index 51274e1..c6b3222 100644
--- a/src/request.rs
+++ b/src/request.rs
@@ -130,7 +130,6 @@
/// The function is used by swoole plugin, to surround the callback of on
/// request.
-#[allow(dead_code)]
pub fn skywalking_hack_swoole_on_request(args: &mut [ZVal]) {
let f = ORI_SWOOLE_ON_REQUEST.load(Ordering::Relaxed);
if f.is_null() {
@@ -161,7 +160,6 @@
}
}
-#[allow(dead_code)]
fn request_init_for_swoole(request: &mut ZVal) -> anyhow::Result<()> {
let request = request
.as_mut_z_obj()
@@ -191,7 +189,6 @@
create_request_context(Some(fd), header.as_deref(), &method, &uri)
}
-#[allow(dead_code)]
fn request_shutdown_for_swoole(response: &mut ZVal) -> anyhow::Result<()> {
let response = response
.as_mut_z_obj()
diff --git a/tests/common/mod.rs b/tests/common/mod.rs
index 6701063..7e9fe85 100644
--- a/tests/common/mod.rs
+++ b/tests/common/mod.rs
@@ -48,6 +48,9 @@
pub const PROXY_SERVER_2_ADDRESS: &str = "127.0.0.1:9012";
pub const FPM_SERVER_1_ADDRESS: &str = "127.0.0.1:9001";
pub const FPM_SERVER_2_ADDRESS: &str = "127.0.0.1:9002";
+pub const SWOOLE_SERVER_1_ADDRESS: &str = "127.0.0.1:9501";
+#[allow(dead_code)]
+pub const SWOOLE_SERVER_2_ADDRESS: &str = "127.0.0.1:9502";
pub const COLLECTOR_GRPC_ADDRESS: &str = "127.0.0.1:19876";
pub const COLLECTOR_HTTP_ADDRESS: &str = "127.0.0.1:12800";
@@ -72,6 +75,8 @@
http_server_2_handle: JoinHandle<()>,
php_fpm_1_child: Child,
php_fpm_2_child: Child,
+ php_swoole_1_child: Child,
+ php_swoole_2_child: Child,
}
pub async fn setup() -> Fixture {
@@ -87,6 +92,8 @@
)),
php_fpm_1_child: setup_php_fpm(1, FPM_SERVER_1_ADDRESS),
php_fpm_2_child: setup_php_fpm(2, FPM_SERVER_2_ADDRESS),
+ php_swoole_1_child: setup_php_swoole(1),
+ php_swoole_2_child: setup_php_swoole(2),
}
}
@@ -97,6 +104,8 @@
let results = join_all([
kill_command(fixture.php_fpm_1_child),
kill_command(fixture.php_fpm_2_child),
+ kill_command(fixture.php_swoole_1_child),
+ kill_command(fixture.php_swoole_2_child),
])
.await;
for result in results {
@@ -247,11 +256,11 @@
let args = [
&php_fpm,
"-F",
- "-n",
+ // "-n",
+ // "-c",
+ // "tests/conf/php.ini",
"-y",
&format!("tests/conf/php-fpm.{}.conf", index),
- "-c",
- "tests/conf/php.ini",
"-d",
&format!("extension=target/{}/libskywalking_agent{}", TARGET, EXT),
"-d",
@@ -286,6 +295,49 @@
.unwrap()
}
+#[instrument]
+fn setup_php_swoole(index: usize) -> Child {
+ let php = env::var("PHP_BIN").unwrap_or_else(|_| "php".to_string());
+ let args = [
+ &php,
+ // "-n",
+ // "-c",
+ // "tests/conf/php.ini",
+ "-d",
+ &format!("extension=target/{}/libskywalking_agent{}", TARGET, EXT),
+ "-d",
+ "skywalking_agent.enable=On",
+ "-d",
+ &format!(
+ "skywalking_agent.service_name=skywalking-agent-test-{}-swoole",
+ index
+ ),
+ "-d",
+ &format!(
+ "skywalking_agent.server_addr=http://{}",
+ COLLECTOR_GRPC_ADDRESS
+ ),
+ "-d",
+ &format!("skywalking_agent.log_level={}", PROCESS_LOG_LEVEL),
+ "-d",
+ &format!(
+ "skywalking_agent.log_file=/tmp/swoole-skywalking-agent.{}.log",
+ index
+ ),
+ "-d",
+ "skywalking.worker_threads=3",
+ &format!("tests/php/swoole/main.{}.php", index),
+ ];
+ info!(cmd = args.join(" "), "start command");
+ Command::new(&args[0])
+ .args(&args[1..])
+ .stdin(Stdio::null())
+ .stdout(File::create("/tmp/swoole-skywalking-stdout.log").unwrap())
+ .stderr(File::create("/tmp/swoole-skywalking-stderr.log").unwrap())
+ .spawn()
+ .unwrap()
+}
+
async fn kill_command(mut child: Child) -> io::Result<ExitStatus> {
if let Some(id) = child.id() {
unsafe {
diff --git a/tests/conf/php.ini b/tests/conf/php.ini
index 81aec1a..8e03302 100644
--- a/tests/conf/php.ini
+++ b/tests/conf/php.ini
@@ -59,44 +59,44 @@
allow_url_include = Off
default_socket_timeout = 60
-extension=mysqlnd.so
-zend_extension=opcache.so
-extension=pdo.so
-extension=xml.so
-extension=bcmath.so
-extension=calendar.so
-extension=ctype.so
-extension=curl.so
-extension=dom.so
-extension=exif.so
-extension=fileinfo.so
-extension=ftp.so
-extension=gd.so
-extension=gettext.so
-extension=iconv.so
-extension=intl.so
-extension=json.so
-extension=mbstring.so
-extension=mysqli.so
-extension=pdo_mysql.so
-extension=phar.so
-extension=posix.so
-extension=readline.so
-; extension=redis.so
-extension=shmop.so
-extension=simplexml.so
-extension=sockets.so
-extension=sysvmsg.so
-extension=sysvsem.so
-extension=sysvshm.so
-extension=swoole.so
-extension=tokenizer.so
-extension=wddx.so
-extension=xmlreader.so
-extension=xmlwriter.so
-extension=xsl.so
-extension=yaml.so
-extension=zip.so
+extension=mysqlnd
+zend_extension=opcache
+extension=pdo
+extension=xml
+extension=bcmath
+extension=calendar
+extension=ctype
+extension=curl
+extension=dom
+extension=exif
+extension=fileinfo
+extension=ftp
+extension=gd
+extension=gettext
+extension=iconv
+extension=intl
+extension=json
+extension=mbstring
+extension=mysqli
+extension=pdo_mysql
+extension=phar
+extension=posix
+extension=readline
+; extension=redis
+extension=shmop
+extension=simplexml
+extension=sockets
+extension=sysvmsg
+extension=sysvsem
+extension=sysvshm
+extension=swoole
+extension=tokenizer
+extension=wddx
+extension=xmlreader
+extension=xmlwriter
+extension=xsl
+extension=yaml
+extension=zip
;;;;;;;;;;;;;;;;;;;
; Module Settings ;
diff --git a/tests/data/expected_context.yaml b/tests/data/expected_context.yaml
index eaf5a98..2ca62ea 100644
--- a/tests/data/expected_context.yaml
+++ b/tests/data/expected_context.yaml
@@ -387,3 +387,110 @@
parentService: skywalking-agent-test-1,
traceId: "not null",
}
+ - serviceName: skywalking-agent-test-1-swoole
+ segmentSize: 2
+ segments:
+ - segmentId: "not null"
+ spans:
+ - operationName: GET:/
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Http
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 8001
+ isError: false
+ spanType: Entry
+ peer: ""
+ skipAnalysis: false
+ tags:
+ - { key: url, value: / }
+ - { key: http.method, value: GET }
+ - { key: http.status_code, value: "200" }
+ refs:
+ - {
+ parentEndpoint: /,
+ networkAddress: "127.0.0.1:9501",
+ refType: CrossProcess,
+ parentSpanId: 1,
+ parentTraceSegmentId: "not null",
+ parentServiceInstance: "not null",
+ parentService: skywalking-agent-test-1-swoole,
+ traceId: "not null",
+ }
+ - segmentId: "not null"
+ spans:
+ - operationName: /
+ parentSpanId: 0
+ spanId: 1
+ spanLayer: Http
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 8002
+ isError: false
+ spanType: Exit
+ peer: 127.0.0.1:9501
+ skipAnalysis: false
+ tags:
+ - { key: url, value: "http://127.0.0.1:9501/" }
+ - { key: status_code, value: "200" }
+ - operationName: /
+ parentSpanId: 0
+ spanId: 2
+ spanLayer: Http
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 8002
+ isError: false
+ spanType: Exit
+ peer: 127.0.0.1:9502
+ skipAnalysis: false
+ tags:
+ - { key: url, value: "http://127.0.0.1:9502/" }
+ - { key: status_code, value: "200" }
+ - operationName: GET:/curl
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Http
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 8001
+ isError: false
+ spanType: Entry
+ peer: ""
+ skipAnalysis: false
+ tags:
+ - { key: url, value: /curl }
+ - { key: http.method, value: GET }
+ - { key: http.status_code, value: "200" }
+ - serviceName: skywalking-agent-test-2-swoole
+ segmentSize: 1
+ segments:
+ - segmentId: "not null"
+ spans:
+ - operationName: GET:/
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Http
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 8001
+ isError: false
+ spanType: Entry
+ peer: ""
+ skipAnalysis: false
+ tags:
+ - { key: url, value: / }
+ - { key: http.method, value: GET }
+ - { key: http.status_code, value: "200" }
+ refs:
+ - {
+ parentEndpoint: /,
+ networkAddress: "127.0.0.1:9502",
+ refType: CrossProcess,
+ parentSpanId: 2,
+ parentTraceSegmentId: "not null",
+ parentServiceInstance: "not null",
+ parentService: skywalking-agent-test-1-swoole,
+ traceId: "not null",
+ }
diff --git a/tests/e2e.rs b/tests/e2e.rs
index 12f9e80..47a6093 100644
--- a/tests/e2e.rs
+++ b/tests/e2e.rs
@@ -15,7 +15,9 @@
mod common;
-use crate::common::{COLLECTOR_HTTP_ADDRESS, HTTP_CLIENT, PROXY_SERVER_1_ADDRESS};
+use crate::common::{
+ COLLECTOR_HTTP_ADDRESS, HTTP_CLIENT, PROXY_SERVER_1_ADDRESS, SWOOLE_SERVER_1_ADDRESS,
+};
use reqwest::{header::CONTENT_TYPE, RequestBuilder, StatusCode};
use std::{
panic::{catch_unwind, resume_unwind},
@@ -46,6 +48,7 @@
async fn run_e2e() {
request_fpm_curl().await;
request_fpm_pdo().await;
+ request_swoole_curl().await;
sleep(Duration::from_secs(3)).await;
request_collector_validate().await;
}
@@ -66,6 +69,14 @@
.await;
}
+async fn request_swoole_curl() {
+ request_common(
+ HTTP_CLIENT.get(format!("http://{}/curl", SWOOLE_SERVER_1_ADDRESS)),
+ "ok",
+ )
+ .await;
+}
+
async fn request_collector_validate() {
request_common(
HTTP_CLIENT
diff --git a/tests/php/swoole/main.1.php b/tests/php/swoole/main.1.php
new file mode 100644
index 0000000..8d0bc7a
--- /dev/null
+++ b/tests/php/swoole/main.1.php
@@ -0,0 +1,82 @@
+<?php
+
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You 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.
+
+use Webmozart\Assert\Assert;
+
+require_once dirname(__DIR__) . "/vendor/autoload.php";
+
+extension_loaded('swoole') or die("extension swoole not loaded");
+
+$http = new Swoole\Http\Server('127.0.0.1', 9501);
+
+$http->set([
+ 'reactor_num' => 3,
+ 'worker_num' => 3,
+ 'enable_coroutine' => true,
+ 'hook_flags' => 0,
+]);
+
+$http->on('start', function ($server) {
+ echo "Swoole http server is started at http://127.0.0.1:9501\n";
+});
+
+$http->on('request', function ($request, $response) {
+ try {
+ switch ($request->server['request_uri']) {
+ case "/":
+ break;
+
+ case "/curl":
+ {
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "http://127.0.0.1:9501/");
+ curl_setopt($ch, CURLOPT_TIMEOUT, 10);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_HEADER, 0);
+ $output = curl_exec($ch);
+ curl_close($ch);
+ Assert::same($output, "ok");
+ }
+
+ {
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "http://127.0.0.1:9502/");
+ curl_setopt($ch, CURLOPT_TIMEOUT, 10);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_HEADER, 0);
+ $output = curl_exec($ch);
+ curl_close($ch);
+ Assert::same($output, "ok");
+ }
+
+ break;
+
+ default:
+ throw new DomainException("Unknown operation");
+ }
+
+ $response->header('Content-Type', 'text/plain');
+ $response->end('ok');
+
+ } catch (Exception $e) {
+ $response->status(500);
+ $response->header('Content-Type', 'text/plain');
+ $response->end($e->getMessage() . "\n" . $e->getTraceAsString());
+ }
+});
+
+$http->start();
diff --git a/tests/php/swoole/main.2.php b/tests/php/swoole/main.2.php
new file mode 100644
index 0000000..1e1a24e
--- /dev/null
+++ b/tests/php/swoole/main.2.php
@@ -0,0 +1,57 @@
+<?php
+
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You 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.
+
+use Webmozart\Assert\Assert;
+
+require_once dirname(__DIR__) . "/vendor/autoload.php";
+
+extension_loaded('swoole') or die("extension swoole not loaded");
+
+$http = new Swoole\Http\Server('127.0.0.1', 9502);
+
+$http->set([
+ 'reactor_num' => 3,
+ 'worker_num' => 3,
+ 'enable_coroutine' => false,
+ 'hook_flags' => 0,
+]);
+
+$http->on('start', function ($server) {
+ echo "Swoole http server is started at http://127.0.0.1:9502\n";
+});
+
+$http->on('request', function ($request, $response) {
+ try {
+ switch ($request->server['request_uri']) {
+ case "/":
+ break;
+
+ default:
+ throw new DomainException("Unknown operation");
+ }
+
+ $response->header('Content-Type', 'text/plain');
+ $response->end('ok');
+
+ } catch (Exception $e) {
+ $response->status(500);
+ $response->header('Content-Type', 'text/plain');
+ $response->end($e->getMessage() . "\n" . $e->getTraceAsString());
+ }
+});
+
+$http->start();