This is an automated email from the ASF dual-hosted git repository.
wu-sheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git
The following commit(s) were added to refs/heads/master by this push:
new bb16533009 Add PHP runtime PHM meter analyzer, e2e, and documentation.
(#13928)
bb16533009 is described below
commit bb16533009a597dbb41ab6f013ac300509abbb3e
Author: songzhendong <[email protected]>
AuthorDate: Thu Jun 25 10:34:00 2026 +0800
Add PHP runtime PHM meter analyzer, e2e, and documentation. (#13928)
Introduce php-runtime.yaml MAL rules for six instance_php_* meters, MAL
tests,
PHP e2e meter assertions, and backend docs. Pin SW_AGENT_PHP_COMMIT to
apache/skywalking-php@de311c9 (PHM #145). Use metrics_report_period=31 in
e2e
php.ini so meter gRPC streams idle-close and OAP persists PHM data.
---
docs/en/changes/changes.md | 5 ++
docs/en/setup/backend/backend-meter.md | 1 +
docs/en/setup/backend/dashboards-php-runtime.md | 73 ++++++++++++++++
docs/menu.yml | 2 +
.../php-runtime.data.yaml | 96 ++++++++++++++++++++++
.../src/main/resources/application.yml | 2 +-
.../meter-analyzer-config/php-runtime.yaml | 33 ++++++++
test/e2e-v2/cases/php/e2e.yaml | 31 +++++++
test/e2e-v2/cases/php/php.ini | 3 +
test/e2e-v2/cases/storage/expected/config-dump.yml | 2 +-
test/e2e-v2/script/env | 2 +-
11 files changed, 247 insertions(+), 3 deletions(-)
diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md
index 82debb79ee..3ef88c95d8 100644
--- a/docs/en/changes/changes.md
+++ b/docs/en/changes/changes.md
@@ -245,6 +245,10 @@
admin-host only" entry above for the public REST retirement.
#### OAP Server
+* Add PHP runtime PHM meter analyzer (`php-runtime.yaml`) for SkyWalking PHP
agent process
+ metrics (CPU, memory, virtual memory, thread count, open file descriptors
sampled from
+ `/proc` on Linux). Registers six `meter_instance_php_*` metrics on the
General Service
+ layer; `php-runtime` is included in the default `meterAnalyzerActiveFiles`.
* Batch the BanyanDB schema fence per runtime-rule apply. A runtime-rule file
changes dozens of rules at once, but the post-DDL fence
(`SchemaWatcher.awaitRevisionApplied`) ran once per metric/downsampling, so a
large file did `K×M` sequential ≤2s fences — on a laggy cluster that overran
the apply's REST budget. The main-node apply path now uses
`StorageManipulationOpt.withSchemaChangeDeferredFence()`: the installer records
each resource's `mod_revision` without fencing and registers a s [...]
* Add a runtime-rule apply-status query. The cluster main now tracks each
structural apply through a phase machine (`SchemaApplyCoordinator`: pending →
DDL → fencing → rolling-out → applied, with `degraded` for a
committed-but-unconfirmed apply — the cluster schema fence did not confirm
within the timeout, in which case the lagging data-node ids are surfaced as
`fenceLaggards` and dispatch is resumed anyway, or the local commit-tail threw
— and `failed` carrying the specific reason). The [...]
* Push runtime-rule convergence to peers on commit. After a successful
structural apply — and on the `commit_deferred` path, where the DB row is
durable but this node's commit-tail threw — the main broadcasts a
`NotifyApplied` admin-internal RPC so peers reconcile against the
just-persisted DB row immediately, instead of waiting up to one refresh tick
(~30s) to notice it. The fan-out runs off the REST response thread
(fire-and-forget on a daemon executor) so an unreachable peer's per-cal [...]
@@ -328,5 +332,6 @@
* Add WeChat / Alipay Mini Program monitoring setup documentation, plus a
client-side-monitoring section in the security guide covering public-internet
ingress (OTLP + `/v3/segments`) for mobile / browser / mini-program SDKs.
* Improve downsampling documentation
* Fix the docker-compose quickstart: OAP healthcheck no longer calls `curl`
(absent from the JRE image) and probes the query port via bash `/dev/tcp`; the
Horizon UI service maps the correct container port (8081) and mounts a
`horizon.yaml` (binding `0.0.0.0`, OAP URLs, demo `admin`/`admin` login)
instead of non-existent `SW_*_ADDRESS` env vars.
+* Add PHP runtime metrics (PHM) dashboard documentation (agent setup, OAP
`php-runtime` MAL rules, Horizon UI widgets).
All issues and pull requests are
[here](https://github.com/apache/skywalking/issues?q=milestone:11.0.0)
diff --git a/docs/en/setup/backend/backend-meter.md
b/docs/en/setup/backend/backend-meter.md
index cf4ee971dc..fa1bf25f5d 100644
--- a/docs/en/setup/backend/backend-meter.md
+++ b/docs/en/setup/backend/backend-meter.md
@@ -53,6 +53,7 @@ All following agents and components have built-in meters
reporting to the OAP th
5. Java agent for thread-pool metrics
6. Rover(eBPF) agent for metrics used continues profiling
7. Satellite proxy self-observability metrics
+8. PHP agent for PHM (PHP Health Metrics) runtime metrics — **Linux only**
(`/proc` sampling)
## Configuration file
diff --git a/docs/en/setup/backend/dashboards-php-runtime.md
b/docs/en/setup/backend/dashboards-php-runtime.md
new file mode 100644
index 0000000000..2c1c905105
--- /dev/null
+++ b/docs/en/setup/backend/dashboards-php-runtime.md
@@ -0,0 +1,73 @@
+# PHP runtime metrics (PHM)
+
+The SkyWalking PHP agent can report **PHP Health Metrics (PHM)** through the
native Meter protocol.
+OAP parses them with MAL rules in `php-runtime.yaml` and stores
+them as `meter_*` metrics on the **General Service** layer.
+
+Requires a PHP agent build that includes PHM (merged in
`apache/skywalking-php` 1.2.0+).
+
+## Platform support
+
+PHM process meters are **Linux only**. In `grpc` / `kafka` reporter mode, the
forked reporter worker
+samples the **parent PHP process** (`getppid()`) through `/proc`
(`/proc/{pid}/status`, `stat`, and
+`fd`). They are not collected on macOS or Windows, and PHM does not run when
`reporter_type =
+standalone`. Instance dashboard widgets stay hidden when no
`meter_instance_php_*` data exists.
+
+## Data flow
+
+1. PHM is **On by default on Linux** when the agent is active
(`skywalking_agent.enable = On`). Set
+ `skywalking_agent.metrics_enable = Off` to disable.
+2. The forked reporter worker boots `skywalking::metrics::Metricer` in
`start_worker` and samples
+ `/proc` on `metrics_report_period` (default 30 seconds). No HTTP traffic is
required.
+3. OAP loads `meter-analyzer-config/php-runtime.yaml` when `php-runtime` is
listed in
+ `agent-analyzer.default.meterAnalyzerActiveFiles`.
+4. Horizon UI renders widgets on **General Service → Instance → Dashboard**
when the corresponding
+ `meter_instance_php_*` metrics exist.
+
+## Agent setup
+
+```ini
+; Default On on Linux when the agent is active.
+; skywalking_agent.metrics_enable = Off
+
+skywalking_agent.metrics_report_period = 30
+```
+
+Refer to the PHP agent README and INI settings documentation for details.
+
+## OAP setup
+
+Ensure `php-runtime` is active (included by default when using the stock
`application.yml`):
+
+```yaml
+agent-analyzer:
+ default:
+ meterAnalyzerActiveFiles: ...,php-runtime,...
+```
+
+## UI location
+
+**Layer:** General Service (`GENERAL`)
+
+**Path:** select a PHP service → **Instance** → **Dashboard**
+
+Widgets appear only when PHM data is present (`visibleWhen` checks each
`meter_instance_php_*` expression).
+
+## Runtime metrics
+
+Agent meter names (reported by the PHP agent) are rewritten by OAP MAL
`metricPrefix: meter`:
+
+| Unit | Agent meter name | OAP / UI metric name
| Description | Data Source
|
+|-------|------------------------------------------|--------------------------------------------|-----------------------------------------|----------------------|
+| % | instance_php_process_cpu_utilization |
meter_instance_php_process_cpu_utilization | Process CPU utilization
| SkyWalking PHP Agent |
+| MB | instance_php_memory_used_mb |
meter_instance_php_memory_used_mb | Resident memory (VmRSS from /proc)
| SkyWalking PHP Agent |
+| MB | instance_php_memory_peak_mb |
meter_instance_php_memory_peak_mb | Peak resident memory (VmHWM from
/proc) | SkyWalking PHP Agent |
+| MB | instance_php_virtual_memory_mb |
meter_instance_php_virtual_memory_mb | Virtual memory (VmSize from /proc)
| SkyWalking PHP Agent |
+| — | instance_php_thread_count |
meter_instance_php_thread_count | OS thread count (Threads from
/proc) | SkyWalking PHP Agent |
+| — | instance_php_open_fd_count |
meter_instance_php_open_fd_count | Open file descriptor count
| SkyWalking PHP Agent |
+
+## Customizations
+
+You can customize MAL expressions or dashboard panels. Metric definitions and
expression rules are in
+`/meter-analyzer-config/php-runtime.yaml`. Instance dashboard widget templates
ship from the
+SkyWalking Horizon UI bundle (`general.json` in apache/skywalking-horizon-ui).
diff --git a/docs/menu.yml b/docs/menu.yml
index 542640bf65..8fee302d14 100644
--- a/docs/menu.yml
+++ b/docs/menu.yml
@@ -260,6 +260,8 @@ catalog:
path: "/en/setup/backend/backend-zabbix"
- name: "Meter Analysis"
path: "/en/setup/backend/backend-meter"
+ - name: "PHP runtime metrics (PHM)"
+ path: "/en/setup/backend/dashboards-php-runtime"
- name: "Telegraf Metrics"
path: "/en/setup/backend/telegraf-receiver"
- name: "Apdex Threshold"
diff --git
a/oap-server/analyzer/meter-analyzer-scripts-test/src/test/resources/scripts/mal/test-meter-analyzer-config/php-runtime.data.yaml
b/oap-server/analyzer/meter-analyzer-scripts-test/src/test/resources/scripts/mal/test-meter-analyzer-config/php-runtime.data.yaml
new file mode 100644
index 0000000000..3a44d8b3a4
--- /dev/null
+++
b/oap-server/analyzer/meter-analyzer-scripts-test/src/test/resources/scripts/mal/test-meter-analyzer-config/php-runtime.data.yaml
@@ -0,0 +1,96 @@
+# 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.
+
+script:
oap-server/server-starter/src/main/resources/meter-analyzer-config/php-runtime.yaml
+input:
+ instance_php_process_cpu_utilization:
+ - labels:
+ instance: test-instance
+ value: 100.0
+ instance_php_memory_used_mb:
+ - labels:
+ instance: test-instance
+ value: 256.0
+ instance_php_memory_peak_mb:
+ - labels:
+ instance: test-instance
+ value: 512.0
+ instance_php_virtual_memory_mb:
+ - labels:
+ instance: test-instance
+ value: 1024.0
+ instance_php_thread_count:
+ - labels:
+ instance: test-instance
+ value: 4.0
+ instance_php_open_fd_count:
+ - labels:
+ instance: test-instance
+ value: 32.0
+expected:
+ meter_instance_php_process_cpu_utilization:
+ entities:
+ - scope: SERVICE_INSTANCE
+ instance: test-instance
+ layer: GENERAL
+ samples:
+ - labels:
+ instance: test-instance
+ value: 100.0
+ meter_instance_php_memory_used_mb:
+ entities:
+ - scope: SERVICE_INSTANCE
+ instance: test-instance
+ layer: GENERAL
+ samples:
+ - labels:
+ instance: test-instance
+ value: 256.0
+ meter_instance_php_memory_peak_mb:
+ entities:
+ - scope: SERVICE_INSTANCE
+ instance: test-instance
+ layer: GENERAL
+ samples:
+ - labels:
+ instance: test-instance
+ value: 512.0
+ meter_instance_php_virtual_memory_mb:
+ entities:
+ - scope: SERVICE_INSTANCE
+ instance: test-instance
+ layer: GENERAL
+ samples:
+ - labels:
+ instance: test-instance
+ value: 1024.0
+ meter_instance_php_thread_count:
+ entities:
+ - scope: SERVICE_INSTANCE
+ instance: test-instance
+ layer: GENERAL
+ samples:
+ - labels:
+ instance: test-instance
+ value: 4.0
+ meter_instance_php_open_fd_count:
+ entities:
+ - scope: SERVICE_INSTANCE
+ instance: test-instance
+ layer: GENERAL
+ samples:
+ - labels:
+ instance: test-instance
+ value: 32.0
diff --git a/oap-server/server-starter/src/main/resources/application.yml
b/oap-server/server-starter/src/main/resources/application.yml
index d38269cfd3..97cd27ee76 100644
--- a/oap-server/server-starter/src/main/resources/application.yml
+++ b/oap-server/server-starter/src/main/resources/application.yml
@@ -229,7 +229,7 @@ agent-analyzer:
# Nginx and Envoy agents can't get the real remote address.
# Exit spans with the component in the list would not generate the
client-side instance relation metrics.
noUpstreamRealAddressAgents: ${SW_NO_UPSTREAM_REAL_ADDRESS:6000,9000}
- meterAnalyzerActiveFiles:
${SW_METER_ANALYZER_ACTIVE_FILES:datasource,threadpool,satellite,go-runtime,python-runtime,continuous-profiling,java-agent,go-agent,ruby-runtime}
# Which files could be meter analyzed, files split by ","
+ meterAnalyzerActiveFiles:
${SW_METER_ANALYZER_ACTIVE_FILES:datasource,threadpool,satellite,go-runtime,python-runtime,continuous-profiling,java-agent,go-agent,ruby-runtime,php-runtime}
# Which files could be meter analyzed, files split by ","
slowCacheReadThreshold:
${SW_SLOW_CACHE_SLOW_READ_THRESHOLD:default:20,redis:10} # The slow cache read
operation thresholds. Unit ms.
slowCacheWriteThreshold:
${SW_SLOW_CACHE_SLOW_WRITE_THRESHOLD:default:20,redis:10} # The slow cache
write operation thresholds. Unit ms.
diff --git
a/oap-server/server-starter/src/main/resources/meter-analyzer-config/php-runtime.yaml
b/oap-server/server-starter/src/main/resources/meter-analyzer-config/php-runtime.yaml
new file mode 100644
index 0000000000..ddc605ae77
--- /dev/null
+++
b/oap-server/server-starter/src/main/resources/meter-analyzer-config/php-runtime.yaml
@@ -0,0 +1,33 @@
+# 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.
+
+expSuffix: instance(['service'], ['instance'], Layer.GENERAL)
+metricPrefix: meter
+metricsRules:
+ # CPU
+ - name: instance_php_process_cpu_utilization
+ exp: instance_php_process_cpu_utilization
+ # Memory
+ - name: instance_php_memory_used_mb
+ exp: instance_php_memory_used_mb
+ - name: instance_php_memory_peak_mb
+ exp: instance_php_memory_peak_mb
+ - name: instance_php_virtual_memory_mb
+ exp: instance_php_virtual_memory_mb
+ # Process resources
+ - name: instance_php_thread_count
+ exp: instance_php_thread_count
+ - name: instance_php_open_fd_count
+ exp: instance_php_open_fd_count
diff --git a/test/e2e-v2/cases/php/e2e.yaml b/test/e2e-v2/cases/php/e2e.yaml
index 0c6c3edff2..93e10f6fd1 100644
--- a/test/e2e-v2/cases/php/e2e.yaml
+++ b/test/e2e-v2/cases/php/e2e.yaml
@@ -107,3 +107,34 @@ verify:
swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql instance list
--service-name=php | yq e '.[0].name' - ) \
--service-name=php --dest-instance-name=provider1
--dest-service-name=e2e-service-provider
expected: expected/metrics-has-value.yml
+ # PHP Health Metrics (PHM) — instance meters via native MeterReportService
+ - query: |
+ swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql metrics exec
--expression=meter_instance_php_process_cpu_utilization --instance-name=$( \
+ swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql instance list
--service-name=php | yq e '.[0].name' - ) \
+ --service-name=php
+ expected: expected/metrics-has-value.yml
+ - query: |
+ swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql metrics exec
--expression=meter_instance_php_memory_used_mb --instance-name=$( \
+ swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql instance list
--service-name=php | yq e '.[0].name' - ) \
+ --service-name=php
+ expected: expected/metrics-has-value.yml
+ - query: |
+ swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql metrics exec
--expression=meter_instance_php_memory_peak_mb --instance-name=$( \
+ swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql instance list
--service-name=php | yq e '.[0].name' - ) \
+ --service-name=php
+ expected: expected/metrics-has-value.yml
+ - query: |
+ swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql metrics exec
--expression=meter_instance_php_virtual_memory_mb --instance-name=$( \
+ swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql instance list
--service-name=php | yq e '.[0].name' - ) \
+ --service-name=php
+ expected: expected/metrics-has-value.yml
+ - query: |
+ swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql metrics exec
--expression=meter_instance_php_thread_count --instance-name=$( \
+ swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql instance list
--service-name=php | yq e '.[0].name' - ) \
+ --service-name=php
+ expected: expected/metrics-has-value.yml
+ - query: |
+ swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql metrics exec
--expression=meter_instance_php_open_fd_count --instance-name=$( \
+ swctl --display yaml
--base-url=http://${oap_host}:${oap_12800}/graphql instance list
--service-name=php | yq e '.[0].name' - ) \
+ --service-name=php
+ expected: expected/metrics-has-value.yml
diff --git a/test/e2e-v2/cases/php/php.ini b/test/e2e-v2/cases/php/php.ini
index ab60122011..985702dad8 100644
--- a/test/e2e-v2/cases/php/php.ini
+++ b/test/e2e-v2/cases/php/php.ini
@@ -25,3 +25,6 @@ skywalking_agent.server_addr = oap:11800
skywalking_agent.skywalking_version = 9
skywalking_agent.runtime_dir = /tmp
+skywalking_agent.metrics_enable = 1
+; CI: 31s (> skywalking-rs 30s stream idle) so OAP meter process() runs
+skywalking_agent.metrics_report_period = 31
diff --git a/test/e2e-v2/cases/storage/expected/config-dump.yml
b/test/e2e-v2/cases/storage/expected/config-dump.yml
index 960e6efc80..f847b69d66 100644
--- a/test/e2e-v2/cases/storage/expected/config-dump.yml
+++ b/test/e2e-v2/cases/storage/expected/config-dump.yml
@@ -32,7 +32,7 @@
"admin-server.default.port": "17128",
"admin-server.provider": "default",
"agent-analyzer.default.forceSampleErrorSegment": "true",
- "agent-analyzer.default.meterAnalyzerActiveFiles":
"datasource,threadpool,satellite,go-runtime,python-runtime,continuous-profiling,java-agent,go-agent,ruby-runtime",
+ "agent-analyzer.default.meterAnalyzerActiveFiles":
"datasource,threadpool,satellite,go-runtime,python-runtime,continuous-profiling,java-agent,go-agent,ruby-runtime,php-runtime",
"agent-analyzer.default.noUpstreamRealAddressAgents": "6000,9000",
"agent-analyzer.default.segmentStatusAnalysisStrategy": "FROM_SPAN_STATUS",
"agent-analyzer.default.slowCacheReadThreshold": "default:20,redis:10",
diff --git a/test/e2e-v2/script/env b/test/e2e-v2/script/env
index 80df253051..de74d3dd64 100644
--- a/test/e2e-v2/script/env
+++ b/test/e2e-v2/script/env
@@ -24,7 +24,7 @@
SW_AGENT_CLIENT_JS_TEST_COMMIT=4f1eb1dcdbde3ec4a38534bf01dded4ab5d2f016
SW_KUBERNETES_COMMIT_SHA=da0e267f877b9b8e5f7728ae4ea7dc7723a2a073
SW_ROVER_COMMIT=79292fe07f17f98f486e0c4471213e1961fb2d1d
SW_BANYANDB_COMMIT=c2d925e4eae4d77edda94e1fd438243483960150
-SW_AGENT_PHP_COMMIT=d1114e7be5d89881eec76e5b56e69ff844691e35
+SW_AGENT_PHP_COMMIT=de311c9cd084e21becade0742cd289bc0f43181d
SW_PREDICTOR_COMMIT=54a0197654a3781a6f73ce35146c712af297c994
SW_CTL_COMMIT=85e5afdb3d55c6e5af66a472c3fe8ac024d11690