This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking-php.git
The following commit(s) were added to refs/heads/master by this push:
new 3187ca1 Add standalone reporter type and standalone skywalking worker
(#119)
3187ca1 is described below
commit 3187ca14711ce5289a3134451af527ee43e954d0
Author: jmjoy <[email protected]>
AuthorDate: Fri Aug 16 18:37:45 2024 +0800
Add standalone reporter type and standalone skywalking worker (#119)
---
docs/en/configuration/ini-settings.md | 10 +-
docs/en/reporter/standalone-reporter.md | 42 +++++++++
docs/menu.yml | 2 +
src/lib.rs | 12 ++-
src/module.rs | 15 ++-
src/worker.rs | 10 +-
worker/Cargo.toml | 8 +-
worker/src/main.rs | 156 ++++++++++++++++++++++++++++++++
worker/src/reporter/reporter_grpc.rs | 2 +-
9 files changed, 242 insertions(+), 15 deletions(-)
diff --git a/docs/en/configuration/ini-settings.md
b/docs/en/configuration/ini-settings.md
index dd883ba..9a35c4d 100644
--- a/docs/en/configuration/ini-settings.md
+++ b/docs/en/configuration/ini-settings.md
@@ -3,7 +3,7 @@
This is the configuration list supported in `php.ini`.
| Configuration Item | Description
| Default Value
|
-| ------------------------------------------------
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
------------------------- |
+| ------------------------------------------------ |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| ------------------------- |
| skywalking_agent.enable | Enable skywalking_agent
extension or not.
| Off
|
| skywalking_agent.log_file | Log file path.
|
/tmp/skywalking-agent.log |
| skywalking_agent.log_level | Log level: one of `OFF`,
`TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`.
| INFO
|
@@ -20,9 +20,9 @@ This is the configuration list supported in `php.ini`.
| skywalking_agent.heartbeat_period | Agent heartbeat report
period. Unit, second.
| 30
|
| skywalking_agent.properties_report_period_factor | The agent sends the
instance properties to the backend every heartbeat_period *
properties_report_period_factor seconds.
| 10 |
| skywalking_agent.enable_zend_observer | Whether to use `zend
observer` instead of `zend_execute_ex` to hook the functions, this feature is
only available for PHP8+.
| Off
|
-| skywalking_agent.reporter_type | Reporter type, optional
values are `grpc` and `kafka`.
| grpc
|
+| skywalking_agent.reporter_type | Reporter type, optional
values are `grpc`, `kafka` and `standalone`.
| grpc
|
| skywalking_agent.kafka_bootstrap_servers | A list of host/port pairs
to use for connect to the Kafka cluster. Only available when `reporter_type` is
`kafka`.
|
|
| skywalking_agent.kafka_producer_config | Configure Kafka Producer
configuration in JSON format `{"key": "value}`. Only available when
`reporter_type` is `kafka`.
| {}
|
-| skywalking_agent.inject_context | Whether to enable
automatic injection of skywalking context variables (such as `SW_TRACE_ID`).
For `php-fpm` mode, it will be injected into the `$_SERVER` variable. For
`swoole` mode, it will be injected into the `$request->server` variable. | Off
|
-| skywalking_agent.instance_name | Instance name. You can
set ${HOSTNAME}, refer to [Example #1](
https://www.php.net/manual/en/install.fpm.configuration.php)
| |
-
+| skywalking_agent.inject_context | Whether to enable
automatic injection of skywalking context variables (such as `SW_TRACE_ID`).
For `php-fpm` mode, it will be injected into the `$_SERVER` variable. For
`swoole` mode, it will be injected into the `$request->server` variable. | Off
|
+| skywalking_agent.instance_name | Instance name. You can
set `${HOSTNAME}`, refer to [Example
#1](https://www.php.net/manual/en/install.fpm.configuration.php)
| |
+| skywalking_agent.standalone_socket_path | Unix domain socket file
path of standalone skywalking php worker. Only available when `reporter_type`
is `standalone`.
|
|
diff --git a/docs/en/reporter/standalone-reporter.md
b/docs/en/reporter/standalone-reporter.md
new file mode 100644
index 0000000..692ab2e
--- /dev/null
+++ b/docs/en/reporter/standalone-reporter.md
@@ -0,0 +1,42 @@
+# Standalone reporter
+
+When the reporter type is `grpc` or `kafka`, the `skywalking_agent` extension
forks a child process during
+the extension initialization phase to act as a worker process for sending data
to the SkyWalking OAP server
+or Kafka.
+
+However, this approach has some limitations, such as:
+
+1. It cannot be used with the `php-fpm` daemon mode.
+2. Multiple worker processes can be redundant when there are several `php-fpm`
processes on the instance.
+
+To address these issues, `skywalking_agent` introduces a new reporter type:
`standalone`.
+
+With the `standalone` reporter type, the `skywalking_agent` extension no
longer forks a child process.
+Instead, the user needs to manually start an independent worker process.
+
+## Steps
+
+1. Compile the standalone `skywalking-php-worker` binary:
+
+ ```shell
+ cargo build -p skywalking-php-worker --bin skywalking-php-worker
--all-features --release
+ ```
+
+2. Run `skywalking-php-worker`:
+
+ Assuming the socket file path is `/tmp/skywalking-php-worker.sock` and the
SkyWalking OAP server address is `127.0.0.1:11800`, the command is:
+
+ ```shell
+ ./target/release/skywalking-php-worker -s /tmp/skywalking-php-worker.sock
grpc --server-addr 127.0.0.1:11800
+ ```
+
+ For additional parameters, refer to `./target/release/skywalking-php-worker
--help`.
+
+3. Configure `php.ini`:
+
+ ```ini
+ [skywalking_agent]
+ extension = skywalking_agent.so
+ skywalking_agent.reporter_type = standalone
+ skywalking_agent.standalone_socket_path = /tmp/skywalking-php-worker.sock
+ ```
diff --git a/docs/menu.yml b/docs/menu.yml
index f7f9e1a..947ffa7 100644
--- a/docs/menu.yml
+++ b/docs/menu.yml
@@ -34,6 +34,8 @@ catalog:
catalog:
- name: "Kafka Reporter"
path: "/en/reporter/kafka-reporter"
+ - name: "Standalone Reporter"
+ path: "/en/reporter/standalone-reporter"
- name: "Contribution"
catalog:
- name: "Compiling Guidance"
diff --git a/src/lib.rs b/src/lib.rs
index 5a54bb9..ceb951d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -91,7 +91,8 @@ const SKYWALKING_AGENT_PROPERTIES_REPORT_PERIOD_FACTOR: &str =
/// PHP8's jit.
const SKYWALKING_AGENT_ENABLE_ZEND_OBSERVER: &str =
"skywalking_agent.enable_zend_observer";
-/// Reporter type, optional values are `grpc` and `kafka`, default is `grpc`.
+/// Reporter type, optional values are `grpc`, `kafka` and `standalone`,
default
+/// is `grpc`.
const SKYWALKING_AGENT_REPORTER_TYPE: &str = "skywalking_agent.reporter_type";
/// A list of host/port pairs to use for establishing the initial connection to
@@ -108,6 +109,10 @@ const SKYWALKING_AGENT_KAFKA_PRODUCER_CONFIG: &str =
"skywalking_agent.kafka_pro
/// `$request->server` variable.
const SKYWALKING_AGENT_INJECT_CONTEXT: &str =
"skywalking_agent.inject_context";
+/// Unix domain socket file path of standalone skywalking php worker. Only
+/// available when `reporter_type` is `standalone`.
+const SKYWALKING_AGENT_STANDALONE_SOCKET_PATH: &str =
"skywalking_agent.standalone_socket_path";
+
#[php_get_module]
pub fn get_module() -> Module {
let mut module = Module::new(
@@ -194,6 +199,11 @@ pub fn get_module() -> Module {
Policy::System,
);
module.add_ini(SKYWALKING_AGENT_INJECT_CONTEXT, false, Policy::System);
+ module.add_ini(
+ SKYWALKING_AGENT_STANDALONE_SOCKET_PATH,
+ "".to_string(),
+ Policy::System,
+ );
// Hooks.
module.on_module_init(module::init);
diff --git a/src/module.rs b/src/module.rs
index a527a48..36a7d74 100644
--- a/src/module.rs
+++ b/src/module.rs
@@ -92,6 +92,12 @@ pub static RUNTIME_DIR: Lazy<PathBuf> = Lazy::new(|| {
});
pub static SOCKET_FILE_PATH: Lazy<PathBuf> = Lazy::new(|| {
+ if is_standalone_reporter_type() {
+ return PathBuf::from(get_str_ini_with_default(
+ SKYWALKING_AGENT_STANDALONE_SOCKET_PATH,
+ ));
+ }
+
let mut dir = RUNTIME_DIR.clone();
let dur = SystemTime::now()
@@ -263,7 +269,9 @@ fn try_init_logger() -> anyhow::Result<()> {
let file = open_options.open(path)?;
- let filter = EnvFilter::new(format!("info,skywalking_agent={}",
log_level));
+ let filter = EnvFilter::new(format!(
+ "info,skywalking_agent={log_level},skywalking_php_worker={log_level}"
+ ));
let subscriber = FmtSubscriber::builder()
.with_env_filter(filter)
@@ -285,3 +293,8 @@ fn get_module_registry() -> &'static ZArr {
pub fn is_enable() -> bool {
*IS_ENABLE
}
+
+#[inline]
+pub fn is_standalone_reporter_type() -> bool {
+ REPORTER_TYPE.as_str() == "standalone"
+}
diff --git a/src/worker.rs b/src/worker.rs
index dbeaa60..145b9fb 100644
--- a/src/worker.rs
+++ b/src/worker.rs
@@ -14,9 +14,9 @@
// limitations under the License.
use crate::module::{
- AUTHENTICATION, ENABLE_TLS, HEARTBEAT_PERIOD,
PROPERTIES_REPORT_PERIOD_FACTOR, REPORTER_TYPE,
- SERVER_ADDR, SERVICE_INSTANCE, SERVICE_NAME, SOCKET_FILE_PATH,
SSL_CERT_CHAIN_PATH,
- SSL_KEY_PATH, SSL_TRUSTED_CA_PATH, WORKER_THREADS,
+ is_standalone_reporter_type, AUTHENTICATION, ENABLE_TLS, HEARTBEAT_PERIOD,
+ PROPERTIES_REPORT_PERIOD_FACTOR, REPORTER_TYPE, SERVER_ADDR,
SERVICE_INSTANCE, SERVICE_NAME,
+ SOCKET_FILE_PATH, SSL_CERT_CHAIN_PATH, SSL_KEY_PATH, SSL_TRUSTED_CA_PATH,
WORKER_THREADS,
};
#[cfg(feature = "kafka-reporter")]
use crate::module::{KAFKA_BOOTSTRAP_SERVERS, KAFKA_PRODUCER_CONFIG};
@@ -31,6 +31,10 @@ use std::{cmp::Ordering, num::NonZeroUsize, process::exit,
thread::available_par
use tracing::error;
pub fn init_worker() {
+ if is_standalone_reporter_type() {
+ return;
+ }
+
unsafe {
// TODO Shutdown previous worker before fork if there is a PHP-FPM
reload
// operation.
diff --git a/worker/Cargo.toml b/worker/Cargo.toml
index 2780dc9..a6f6d82 100644
--- a/worker/Cargo.toml
+++ b/worker/Cargo.toml
@@ -43,9 +43,9 @@ skywalking = { version = "0.8.0", features = ["management"] }
tokio = { version = "1.29.1", features = ["full"] }
tokio-stream = "0.1.14"
tonic = { version = "0.8.3", features = ["tls", "tls-roots"] }
-tracing = { version = "0.1.37", features = ["attributes"] }
+tracing = { version = "0.1.37", features = ["attributes", "log"] }
tracing-subscriber = { version = "0.3.17", features = ["env-filter"], optional
= true }
-# [[bin]]
-# name = "skywalking-php-worker"
-# required-features = ["standalone", "kafka-reporter"]
+[[bin]]
+name = "skywalking-php-worker"
+required-features = ["standalone", "kafka-reporter"]
diff --git a/worker/src/main.rs b/worker/src/main.rs
new file mode 100644
index 0000000..d924e1f
--- /dev/null
+++ b/worker/src/main.rs
@@ -0,0 +1,156 @@
+// 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 clap::Parser;
+use skywalking_php_worker::{
+ new_tokio_runtime,
+ reporter::{GrpcReporterConfiguration, KafkaReporterConfiguration,
ReporterConfiguration},
+ start_worker, WorkerConfiguration,
+};
+use std::{num::NonZeroUsize, path::PathBuf, thread::available_parallelism};
+use tracing::log::LevelFilter;
+use tracing_subscriber::{EnvFilter, FmtSubscriber};
+
+#[derive(Parser, Debug)]
+#[command(version, about, long_about = None)]
+struct Args {
+ /// Path of socket file to listening
+ #[arg(short, long)]
+ socket_file_path: PathBuf,
+
+ /// Count of worker threads, default is `nproc`
+ #[arg(long)]
+ worker_threads: Option<usize>,
+
+ /// Log level, will be overwritten by env `RUST_LOG`
+ #[arg(short, long, default_value = "INFO")]
+ log_level: LevelFilter,
+
+ /// Select reporter
+ #[command(subcommand)]
+ reporter: ReporterArgs,
+}
+
+#[derive(Parser, Debug)]
+#[command(version, about, long_about = None)]
+enum ReporterArgs {
+ /// Report to Skywalking OAP via grpc protocol
+ Grpc {
+ /// skywalking server address
+ #[arg(long)]
+ server_addr: String,
+
+ /// Skywalking agent authentication token
+ #[arg(long)]
+ authentication: Option<String>,
+
+ /// Wether to enable tls for gPRC
+ #[arg(long)]
+ enable_tls: bool,
+
+ /// The gRPC SSL trusted ca file
+ #[arg(long, required_if_eq("enable_tls", "true"))]
+ ssl_cert_chain_path: Option<String>,
+
+ /// The private key file. Enable mTLS when ssl_key_path and
+ /// ssl_cert_chain_path exist
+ #[arg(long)]
+ ssl_key_path: Option<String>,
+
+ /// The certificate file. Enable mTLS when ssl_key_path and
+ /// ssl_cert_chain_path exist
+ #[arg(long)]
+ ssl_trusted_ca_path: Option<String>,
+ },
+ /// Report to kafka
+ Kafka {
+ /// A list of host/port pairs to use for establishing the initial
+ /// connection to the Kafka cluster. Only available when the
+ /// reporter type is `kafka`
+ #[arg(long)]
+ kafka_bootstrap_servers: String,
+
+ /// Configure Kafka Producer configuration in JSON format.
+ /// Only available when the reporter type is `kafka`
+ #[arg(long)]
+ kafka_producer_config: Option<String>,
+ },
+}
+
+impl From<ReporterArgs> for ReporterConfiguration {
+ fn from(args: ReporterArgs) -> Self {
+ match args {
+ ReporterArgs::Grpc {
+ server_addr,
+ authentication,
+ enable_tls,
+ ssl_cert_chain_path,
+ ssl_key_path,
+ ssl_trusted_ca_path,
+ } => ReporterConfiguration::Grpc(GrpcReporterConfiguration {
+ server_addr,
+ authentication: authentication.unwrap_or_default(),
+ enable_tls,
+ ssl_cert_chain_path: ssl_cert_chain_path.unwrap_or_default(),
+ ssl_key_path: ssl_key_path.unwrap_or_default(),
+ ssl_trusted_ca_path: ssl_trusted_ca_path.unwrap_or_default(),
+ }),
+ ReporterArgs::Kafka {
+ kafka_bootstrap_servers,
+ kafka_producer_config,
+ } => ReporterConfiguration::Kafka(KafkaReporterConfiguration {
+ kafka_bootstrap_servers,
+ kafka_producer_config:
kafka_producer_config.unwrap_or_default(),
+ }),
+ }
+ }
+}
+
+fn init_logger(log_level: &LevelFilter) -> anyhow::Result<()> {
+ let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| {
+ EnvFilter::new(format!(
+
"info,skywalking_agent={log_level},skywalking_php_worker={log_level}"
+ ))
+ });
+
+ let subscriber = FmtSubscriber::builder()
+ .with_env_filter(filter)
+ .with_ansi(false)
+ .finish();
+
+ tracing::subscriber::set_global_default(subscriber)?;
+
+ Ok(())
+}
+
+fn worker_threads(worker_threads: Option<usize>) -> usize {
+ worker_threads.unwrap_or_else(||
available_parallelism().map(NonZeroUsize::get).unwrap_or(1))
+}
+
+fn main() -> anyhow::Result<()> {
+ let args = Args::parse();
+
+ init_logger(&args.log_level)?;
+
+ let rt = new_tokio_runtime(worker_threads(args.worker_threads));
+
+ rt.block_on(start_worker(WorkerConfiguration {
+ socket_file_path: args.socket_file_path,
+ heart_beat: None,
+ reporter_config: args.reporter.into(),
+ }))?;
+
+ Ok(())
+}
diff --git a/worker/src/reporter/reporter_grpc.rs
b/worker/src/reporter/reporter_grpc.rs
index d450b43..fdbdd18 100644
--- a/worker/src/reporter/reporter_grpc.rs
+++ b/worker/src/reporter/reporter_grpc.rs
@@ -21,9 +21,9 @@ use tonic::transport::{Certificate, Channel, ClientTlsConfig,
Endpoint, Identity
use tracing::{debug, info, warn};
pub struct GrpcReporterConfiguration {
+ pub server_addr: String,
pub authentication: String,
pub enable_tls: bool,
- pub server_addr: String,
pub ssl_cert_chain_path: String,
pub ssl_key_path: String,
pub ssl_trusted_ca_path: String,