├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── ci.yml ├── .gitignore ├── .gitmodules ├── .licenserc.yaml ├── CREDITS ├── Cargo.lock ├── Cargo.toml ├── EXPERIMENTAL ├── LICENSE ├── README.md ├── build.rs ├── config.m4 ├── config.w32 ├── docker ├── Dockerfile ├── entrypoint.sh ├── index.php └── nginx.conf ├── docs ├── API.md ├── BUILDING.md ├── CONFIG.md ├── README.md └── quick-start.md ├── e2e ├── 99-skywalking.ini ├── composer.json ├── docker-compose.yml ├── e2e.php ├── index.php ├── init.sql ├── nginx.conf ├── override.conf ├── tests.php └── tests │ ├── functions.php │ ├── memcached.php │ ├── mysqli.php │ ├── redis.php │ └── yar.php ├── go.mod ├── go.sum ├── package.xml ├── php.ini ├── php_skywalking.h ├── rust-toolchain.toml ├── scripts ├── generate-protocol.sh ├── package.py ├── pecl.sh └── version.sh ├── skywalking.c ├── skywalking.php ├── src ├── reporter │ ├── grpc.rs │ ├── ipc.rs │ └── mod.rs ├── sky_base.h ├── sky_core_cross_process.c ├── sky_core_cross_process.h ├── sky_core_log.c ├── sky_core_log.h ├── sky_core_module.c ├── sky_core_module.h ├── sky_core_report.h ├── sky_core_report.rs ├── sky_core_segment.c ├── sky_core_segment.h ├── sky_core_segment_reference.c ├── sky_core_segment_reference.h ├── sky_core_span.c ├── sky_core_span.h ├── sky_core_tag.c ├── sky_core_tag.h ├── sky_execute.cc ├── sky_execute.h ├── sky_log.cc ├── sky_log.h ├── sky_module.cc ├── sky_module.h ├── sky_pdo.cc ├── sky_pdo.h ├── sky_plugin_curl.c ├── sky_plugin_curl.h ├── sky_plugin_error.cc ├── sky_plugin_error.h ├── sky_plugin_grpc.cc ├── sky_plugin_grpc.h ├── sky_plugin_hyperf_guzzle.cc ├── sky_plugin_hyperf_guzzle.h ├── sky_plugin_memcached.cc ├── sky_plugin_memcached.h ├── sky_plugin_mysqli.cc ├── sky_plugin_mysqli.h ├── sky_plugin_predis.cc ├── sky_plugin_predis.h ├── sky_plugin_rabbit_mq.cc ├── sky_plugin_rabbit_mq.h ├── sky_plugin_redis.c ├── sky_plugin_redis.h ├── sky_plugin_swoole_curl.cc ├── sky_plugin_swoole_curl.h ├── sky_plugin_yar.cc ├── sky_plugin_yar.h ├── sky_rate_limit.cc ├── sky_rate_limit.h ├── sky_util_base64.c ├── sky_util_base64.h ├── sky_util_php.c ├── sky_util_php.h ├── sky_utils.c └── sky_utils.h └── swoole.php /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **PHP (please complete the following information):** 27 | - OS: [e.g. Centos] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 7.0.0] 30 | - PHP ini 31 | 32 | **SkyWalking (please complete the following information):** 33 | - OS: [e.g. Centos] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 6.4] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021 SkyAPM 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | name: CI 17 | 18 | on: 19 | push: 20 | branches: 21 | - master 22 | tags: 23 | - 'v*' 24 | pull_request: 25 | branches: 26 | - master 27 | 28 | jobs: 29 | build: 30 | runs-on: ${{ matrix.operating-system }} 31 | strategy: 32 | matrix: 33 | operating-system: [ubuntu-latest] 34 | php-version: ['8.1', '8.0', '7.4', '7.3', '7.2', '7.1', '7.0'] 35 | skywalking-version: ['9.0.0', '8.9.1', '8.9.0', '8.8.1', '8.7.0-es7', '8.7.0-es6', '8.6.0-es7', '8.6.0-es6', '8.5.0-es6', '8.4.0-es6'] 36 | name: PHP ${{ matrix.php-version }} Test on SW ${{ matrix.skywalking-version }} 37 | services: 38 | skywalking: 39 | image: apache/skywalking-oap-server:${{ matrix.skywalking-version }} 40 | ports: 41 | - 11800:11800 42 | - 12800:12800 43 | mysql: 44 | image: mysql:5 45 | ports: 46 | - 3306:3306 47 | env: 48 | MYSQL_ROOT_PASSWORD: password 49 | MYSQL_DATABASE: "skywalking" 50 | options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 51 | redis: 52 | image: redis 53 | ports: 54 | - 6379:6379 55 | options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3 56 | memcached: 57 | image: memcached 58 | ports: 59 | - 11211:11211 60 | steps: 61 | - name: Checkout 62 | uses: actions/checkout@v2 63 | with: 64 | submodules: 'true' 65 | 66 | - name: Check License 67 | uses: apache/skywalking-eyes/header@501a28d2fb4a9b962661987e50cf0219631b32ff 68 | 69 | - name: Setup PHP 70 | uses: shivammathur/setup-php@v2 71 | env: 72 | YAR_LIBS: libcurl4-openssl-dev 73 | with: 74 | php-version: ${{ matrix.php-version }} 75 | extensions: curl, json, redis, pdo_mysql, memcached, yar-laruence/yar@yar-2.2.0 76 | tools: php-config, phpize, composer 77 | 78 | - name: Install library 79 | run: | 80 | sudo apt-get update 81 | sudo apt-get install -y curl libcurl4-openssl-dev nginx 82 | sudo apt-get install -y build-essential autoconf libtool pkg-config cmake 83 | sudo apt-get install -y autoconf automake libtool curl make g++ unzip 84 | if ! [ -e /usr/bin/php-fpm ]; then 85 | sudo apt-get install -y php${{ matrix.php-version }}-fpm 86 | sudo cp /usr/sbin/php-fpm${{ matrix.php-version }} /usr/bin/php-fpm 87 | fi 88 | cd e2e 89 | composer install 90 | cd .. 91 | 92 | - name: Build SkyWalking-PHP 93 | run: | 94 | cd /home/runner/work/SkyAPM-php-sdk/SkyAPM-php-sdk 95 | phpize 96 | ./configure 97 | make -j$(nproc) 98 | sudo make install 99 | 100 | - name: Start FPM and Nginx 101 | run: | 102 | ulimit -c unlimited 103 | sudo cp e2e/99-skywalking.ini $(php -i | grep 'additional .ini' | sed -e "s|.*=> s*||") 104 | sudo cp e2e/99-skywalking.ini $(php-fpm -i | grep 'additional .ini' | sed -e "s|.*=> s*||") 105 | sudo cp e2e/nginx.conf /etc/nginx/conf.d/ 106 | sudo sed -i "s/VERSION/${{ matrix.php-version }}/g" /etc/nginx/conf.d/nginx.conf 107 | sudo cp -r e2e/vendor e2e/tests /var/www/html/ 108 | sudo cp e2e/tests.php e2e/index.php /var/www/html/ 109 | sudo systemctl restart php${{ matrix.php-version }}-fpm 110 | sudo systemctl restart nginx 111 | sleep 15 112 | 113 | 114 | - name: E2E tests 115 | run: | 116 | ulimit -c unlimited 117 | cd e2e 118 | sudo php -dskywalking.enable=0 e2e.php ${{ matrix.php-version }} 119 | sudo cat /tmp/skywalking-php.log 120 | 121 | - uses: actions/upload-artifact@v2 122 | if: failure() 123 | with: 124 | name: crashes 125 | path: /var/crash 126 | 127 | publish: 128 | if: github.repository == 'SkyAPM/SkyAPM-php-sdk' 129 | runs-on: ubuntu-latest 130 | permissions: 131 | contents: read 132 | packages: write 133 | strategy: 134 | matrix: 135 | php-version: ['8.1', '8.0', '7.4', '7.3', '7.2', '7.1', '7.0'] 136 | name: Publish PHP ${{ matrix.php-version }} 137 | steps: 138 | - name: Checkout 139 | uses: actions/checkout@v2 140 | with: 141 | submodules: 'true' 142 | 143 | - name: Log in to Docker Hub 144 | uses: docker/login-action@v1 145 | with: 146 | username: ${{ secrets.DOCKER_USERNAME }} 147 | password: ${{ secrets.DOCKER_PASSWORD }} 148 | if: ${{ github.event_name != 'pull_request' }} 149 | 150 | - name: Log in to the Container registry 151 | uses: docker/login-action@v1 152 | with: 153 | registry: ghcr.io 154 | username: ${{ github.actor }} 155 | password: ${{ secrets.GITHUB_TOKEN }} 156 | if: ${{ github.event_name != 'pull_request' }} 157 | 158 | - name: Extract metadata for Docker 159 | id: meta 160 | uses: docker/metadata-action@v3 161 | with: 162 | images: | 163 | skyapm/skywalking-php 164 | ghcr.io/skyapm/skywalking-php 165 | 166 | - name: Set output 167 | id: vars 168 | run: echo ::set-output name=tag::$(echo ${GITHUB_REF#refs/*/} | sed "s/\//\-/") 169 | 170 | - name: Check output 171 | run: echo ${{ steps.vars.outputs.tag }} 172 | 173 | - name: Build and push 174 | uses: docker/build-push-action@v2 175 | with: 176 | context: . 177 | file: docker/Dockerfile 178 | build-args: PHP_VERSION=${{ matrix.php-version }} 179 | push: ${{ github.event_name != 'pull_request' }} 180 | tags: | 181 | skyapm/skywalking-php:${{ steps.vars.outputs.tag }}-${{ matrix.php-version }}-fpm-alpine 182 | ghcr.io/skyapm/skywalking-php:${{ steps.vars.outputs.tag }}-${{ matrix.php-version }}-fpm-alpine 183 | labels: ${{ steps.meta.outputs.labels }} 184 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021 SkyAPM 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | .deps 17 | .DS_Store 18 | .idea 19 | target 20 | cmake-build-debug-remote 21 | cmake-build-debug 22 | CMakeLists.txt 23 | /configure.ac 24 | /skywalking.loT 25 | *.lo 26 | *.la 27 | *.dep 28 | .libs 29 | /acinclude.m4 30 | /aclocal.m4 31 | /autom4te.cache 32 | /build 33 | /config.guess 34 | /config.h 35 | /config.h.in~ 36 | /config.h.in 37 | /config.log 38 | /config.nice 39 | /config.status 40 | /config.sub 41 | /configure 42 | /configure.in 43 | /include 44 | /install-sh 45 | /libtool 46 | /ltmain.sh 47 | /Makefile 48 | /Makefile.fragments 49 | /Makefile.global 50 | /Makefile.objects 51 | /missing 52 | /mkinstalldirs 53 | /modules 54 | /run-tests.php 55 | /tests/*/*.diff 56 | /tests/*/*.out 57 | /tests/*/*.php 58 | /tests/*/*.exp 59 | /tests/*/*.log 60 | /tests/*/*.sh 61 | sky_php* 62 | /src/network/* 63 | log.cpp 64 | skywalking*.tgz 65 | e2e/composer.lock 66 | e2e/vendor 67 | vendor 68 | composer.* 69 | /.vscode 70 | configure~ 71 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/protocol"] 2 | path = src/protocol 3 | url = https://github.com/apache/skywalking-data-collect-protocol.git 4 | -------------------------------------------------------------------------------- /.licenserc.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021 SkyAPM 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | header: 17 | license: 18 | spdx-id: Apache-2.0 19 | copyright-owner: SkyAPM 20 | 21 | paths-ignore: 22 | - '.gitmodules' 23 | - 'configure~' 24 | - 'dist' 25 | - 'licenses' 26 | - '**/*.md' 27 | - '**/*.o' 28 | - '**/*.a' 29 | - '**/*.lo' 30 | - '**/*.dep' 31 | - 'target' 32 | - 'Cargo.lock' 33 | - 'LICENSE' 34 | - 'NOTICE' 35 | - 'CREDITS' 36 | - 'EXPERIMENTAL' 37 | - 'config.m4' 38 | - 'config.w32' 39 | - 'config.w32' 40 | - 'go.mod' 41 | - 'go.sum' 42 | - 'src/protocol' 43 | - 'src/collect' 44 | - 'e2e/composer.json' 45 | 46 | comment: on-failure -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | skywalking -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 SkyAPM 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | [package] 16 | name = "SkyAPM-php-sdk" 17 | version = "1.0.0" 18 | edition = "2021" 19 | authors = ["Yanlong He "] 20 | 21 | [dependencies] 22 | tonic = "0.5.2" 23 | prost = "0.8.0" 24 | prost-derive = "0.8.0" 25 | tokio = { version = "1", features = ["full"] } 26 | gethostname = "0.2.3" 27 | local-ip-address = "0.4.4" 28 | uuid = { version = "1.0.0", features = ["v4"] } 29 | serde = { version = "1.0", features = ["serde_derive"] } 30 | serde_json = "1.0" 31 | futures-util = "0.3.21" 32 | rand = "0.8.5" 33 | log = "0.4.1" 34 | anyhow = "1.0.57" 35 | ipc-channel = "0.16.0" 36 | simplelog = "0.12.0" 37 | 38 | 39 | [build-dependencies] 40 | tonic-build = "0.5.2" 41 | cbindgen = "0.23.0" 42 | 43 | [lib] 44 | name = "sky_core_report" 45 | crate-type = ["staticlib"] 46 | path = "src/sky_core_report.rs" 47 | -------------------------------------------------------------------------------- /EXPERIMENTAL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SkyAPM/SkyAPM-php-sdk/205bfc1c1d15c1fe1f45821a0948562df7bbdec2/EXPERIMENTAL -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This agent is being replaced by upstream [SkyWalking PHP Agent](https://github.com/apache/skywalking-php) 2 | 3 | ~~SkyAPM PHP~~ 4 | ========== 5 | ![CI](https://github.com/SkyAPM/SkyAPM-php-sdk/workflows/CI/badge.svg) 6 | ![release](https://img.shields.io/github/release/SkyAPM/SkyAPM-php-sdk.svg) 7 | ![PHP](https://img.shields.io/badge/PHP-%3E%3D%207.0-brightgreen.svg) 8 | ![contributors](https://img.shields.io/github/contributors/SkyAPM/SkyAPM-php-sdk.svg) 9 | ![platform](https://img.shields.io/badge/platform-macos%20%7C%20linux-brightgreen.svg) 10 | ![license](https://img.shields.io/badge/license-Apache%202.0-green.svg) 11 | ![issues](https://img.shields.io/github/issues/SkyAPM/SkyAPM-php-sdk.svg) 12 | 13 | 14 | Sky Walking logo 15 | 16 | **SkyAPM PHP** is the PHP instrumentation agent, which is compatible with [Apache SkyWalking](https://github.com/apache/skywalking) backend and others compatible agents/SDKs 17 | 18 | ## Support List 19 | 1. cURL ([PHP cURL](https://www.php.net/manual/en/book.curl.php)) 20 | 2. PDO ([PHP PDO](https://www.php.net/manual/en/book.pdo.php)) 21 | 3. Mysqli ([PHP Mysqli](https://www.php.net/manual/en/book.mysqli.php)) 22 | 4. Redis Extension ([Redis Extension](https://github.com/phpredis/phpredis)) 23 | 5. Predis Client ([Predis](https://packagist.org/packages/predis/predis)) 24 | 6. Memcache Extension ([Memcache Extension](https://www.php.net/manual/en/book.memcached.php)) 25 | 7. Yar Client (version > 2.0.4) ([Yar](https://www.php.net/manual/en/book.yar.php)) 26 | 8. Yar Server ([Yar](https://www.php.net/manual/en/book.yar.php)) 27 | 9. GRPC Client ([GRPC](https://github.com/grpc/grpc-php)) 28 | 10. RabbitMQ 29 | 30 | ## Support List (Swoole ecosystem) 31 | 11. Swoole ([Swoole](https://github.com/swoole/swoole-src)) 32 | 12. Hyperf ([Hyperf](https://github.com/hyperf/hyperf)) 33 | 13. Swoft ([Swoft](https://github.com/swoft-cloud/swoft)) 34 | 14. Tars-php ([Tars-php](https://github.com/TarsPHP/TarsPHP)) 35 | 15. LaravelS ([LaravelS](https://github.com/hhxsv5/laravel-s)) 36 | 37 | ## Documentation 38 | * [Official documentation](docs/README.md) 39 | 40 | ## Docker image (Quick start) 41 | Go to Docker hub -> [https://hub.docker.com/u/skyapm](https://hub.docker.com/u/skyapm) 42 | ```shell script 43 | $ docker run --restart always -d -e SW_OAP_ADDRESS=oap:11800 skyapm/skywalking-php 44 | ``` 45 | 46 | ## Downloads 47 | Please head to the [releases page](https://pecl.php.net/package/skywalking) to download a release of SkyAPM PHP. 48 | 49 | ## Stargazers over time 50 | 51 | [![Stargazers over time](https://starchart.cc/SkyAPM/SkyAPM-php-sdk.svg)](https://starchart.cc/SkyAPM/SkyAPM-php-sdk) 52 | 53 | ## License 54 | [Apache 2.0](LICENSE) 55 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 SkyAPM 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | fn main() -> Result<(), Box> { 16 | tonic_build::configure() 17 | .build_server(false) 18 | .type_attribute(".", "#[derive(::serde::Deserialize)]") 19 | // .type_attribute(".", "#[serde(default)]") 20 | .compile( 21 | &[ 22 | "./src/protocol/language-agent/Tracing.proto", 23 | "./src/protocol/management/Management.proto", 24 | ], 25 | &["./src/protocol/"], 26 | )?; 27 | Ok(()) 28 | } -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | PHP_ARG_ENABLE([skywalking], 2 | [whether to enable skywalking support], 3 | [AS_HELP_STRING([--enable-skywalking], 4 | [Enable skywalking support])], 5 | [yes]) 6 | 7 | if test "$PHP_THREAD_SAFETY" == "yes"; then 8 | AC_MSG_ERROR([skywalking does not support ZTS]) 9 | fi 10 | 11 | if test "$PHP_SKYWALKING" != "no"; then 12 | AC_PATH_PROG(CARGO, cargo, no) 13 | if ! test -x "$CARGO"; then 14 | AC_MSG_ERROR([cargo command missing, please reinstall the cargo distribution]) 15 | fi 16 | AC_PATH_PROG(RUSTFMT, rustfmt, no) 17 | if ! test -x "$RUSTFMT"; then 18 | AC_MSG_ERROR([rustfmt command missing, please reinstall the cargo distribution]) 19 | fi 20 | 21 | EXTRA_LDFLAGS="$EXTRA_LDFLAGS $srcdir/target/release/libsky_core_report.a" 22 | LIBS="-lpthread $LIBS" 23 | 24 | SKYWALKING_SHARED_LIBADD="-lpthread $SKYWALKING_SHARED_LIBADD" 25 | PHP_ADD_LIBRARY(pthread) 26 | PHP_ADD_LIBRARY(dl,,SKYWALKING_SHARED_LIBADD) 27 | PHP_ADD_LIBRARY(dl) 28 | case $host in 29 | *darwin*) 30 | ;; 31 | *) 32 | PHP_ADD_LIBRARY(rt,,SKYWALKING_SHARED_LIBADD) 33 | PHP_ADD_LIBRARY(rt) 34 | ;; 35 | esac 36 | 37 | PHP_SUBST(SKYWALKING_SHARED_LIBADD) 38 | 39 | PHP_ADD_INCLUDE(src) 40 | AC_DEFINE(HAVE_SKYWALKING, 1, [ Have skywalking support ]) 41 | 42 | PHP_NEW_EXTENSION(skywalking, \ 43 | skywalking.c \ 44 | src/sky_core_cross_process.c \ 45 | src/sky_core_log.c \ 46 | src/sky_core_module.c \ 47 | src/sky_core_segment.c \ 48 | src/sky_core_segment_reference.c \ 49 | src/sky_core_span.c \ 50 | src/sky_core_tag.c \ 51 | src/sky_plugin_curl.c \ 52 | src/sky_plugin_redis.c \ 53 | src/sky_util_base64.c \ 54 | src/sky_util_php.c \ 55 | src/sky_utils.c \ 56 | , $ext_shared) 57 | PHP_ADD_BUILD_DIR($ext_builddir/src) 58 | fi 59 | 60 | if test -r $phpincludedir/ext/mysqli/mysqli_mysqlnd.h; then 61 | AC_DEFINE([MYSQLI_USE_MYSQLND], 1, [Whether mysqlnd is enabled]) 62 | fi 63 | shared_objects_skywalking="$srcdir/target/release/libsky_core_report.a $shared_objects_skywalking" 64 | dnl PHP_SUBST(shared_objects_skywalking) 65 | case $host in 66 | *darwin*) 67 | echo "$srcdir/target/release/libsky_core_report.a:\n cargo build --release --manifest-path=$srcdir/Cargo.toml" >> Makefile.objects 68 | ;; 69 | *) 70 | echo -e "$srcdir/target/release/libsky_core_report.a:\n cargo build --release --manifest-path=$srcdir/Cargo.toml" >> Makefile.objects 71 | ;; 72 | esac -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | // $Id$ 2 | // vim:ft=javascript 3 | 4 | // If your extension references something external, use ARG_WITH 5 | // ARG_WITH("skywalking", "for skywalking support", "no"); 6 | 7 | // Otherwise, use ARG_ENABLE 8 | // ARG_ENABLE("skywalking", "enable skywalking support", "no"); 9 | 10 | if (PHP_SKYWALKING != "no") { 11 | EXTENSION("skywalking", "skywalking.c", PHP_EXTNAME_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021 SkyAPM 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | ARG PHP_VERSION 17 | FROM php:${PHP_VERSION}-fpm-alpine 18 | 19 | ADD . /var/local/git/skywalking 20 | 21 | ENV PROTOBUF_VERSION 3.14.0 22 | ENV PROTOBUF_URL https://github.com/protocolbuffers/protobuf/releases/download/v"$PROTOBUF_VERSION"/protobuf-cpp-"$PROTOBUF_VERSION".zip 23 | ENV RUSTFLAGS="-Ctarget-feature=-crt-static" 24 | 25 | RUN set -ex \ 26 | && docker-php-ext-install mysqli \ 27 | && apk --update add --no-cache git ca-certificates build-base unzip autoconf automake libtool g++ make file linux-headers file re2c pkgconf openssl openssl-dev curl-dev nginx \ 28 | && curl https://sh.rustup.rs -sSf | sh -s -- -y \ 29 | && source $HOME/.cargo/env \ 30 | && curl --silent -L -o protobuf.zip "$PROTOBUF_URL" \ 31 | && unzip protobuf.zip \ 32 | && cd protobuf-"$PROTOBUF_VERSION" \ 33 | && ./configure && make -j$(nproc) && make install \ 34 | && cd .. && rm protobuf.zip \ 35 | && echo "--- installing skywalking php ---" \ 36 | && cd /var/local/git/skywalking \ 37 | && git submodule update --init \ 38 | && phpize && ./configure && make -j$(nproc) && make install \ 39 | && cp php.ini $PHP_INI_DIR/conf.d/ext-skywalking.ini \ 40 | && mkdir -p /opt \ 41 | && cp docker/entrypoint.sh /opt/ \ 42 | && cp docker/nginx.conf /etc/nginx/nginx.conf \ 43 | && cp docker/index.php /var/www/html/index.php \ 44 | && cd / \ 45 | && rm -rf /var/cache/apk/* \ 46 | && rm -fr /var/local/git 47 | 48 | EXPOSE 9000 49 | EXPOSE 8080 50 | 51 | ENTRYPOINT ["/opt/entrypoint.sh"] -------------------------------------------------------------------------------- /docker/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # 3 | # Copyright 2021 SkyAPM 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | grpc=$SW_OAP_ADDRESS 19 | 20 | if [ ! $grpc ]; then 21 | grpc="127.0.0.1:11800" 22 | else 23 | sed -i "s/127.0.0.1:11800/$grpc/g" $PHP_INI_DIR/conf.d/ext-skywalking.ini 24 | fi 25 | 26 | echo "skywalking oap address:" $grpc 27 | 28 | nginx 29 | 30 | php-fpm 31 | -------------------------------------------------------------------------------- /docker/index.php: -------------------------------------------------------------------------------- 1 | startTime = time() - 15 * 60; 71 | } 72 | 73 | public function query($query, $variables) { 74 | $client = new \GuzzleHttp\Client(); 75 | 76 | $json = [ 77 | 'query' => $query, 78 | 'variables' => $variables 79 | ]; 80 | 81 | $this->info("query request body: " . json_encode($json)); 82 | $res = $client->request("POST", $this->url, [ 83 | 'json' => $json 84 | ]); 85 | 86 | $this->info("query response status code: " . $res->getStatusCode()); 87 | if ($res->getStatusCode() != 200) { 88 | return ""; 89 | } 90 | 91 | $body = $res->getBody()->getContents(); 92 | $this->info("query response body: " . $body); 93 | return $body; 94 | } 95 | 96 | public function info($msg) { 97 | echo chr(27) . "[1;34m" . $msg . chr(27) . "[0m\n"; 98 | } 99 | 100 | public function call() { 101 | $ch = curl_init('http://127.0.0.1:8083/call'); 102 | curl_exec($ch); 103 | if (curl_getinfo($ch, CURLINFO_HTTP_CODE) != 200) { 104 | return false; 105 | } 106 | return true; 107 | } 108 | 109 | public function verifyServices() { 110 | $variables = [ 111 | 'duration' => [ 112 | "start" => date("Y-m-d His", $this->startTime), 113 | "end" => date("Y-m-d His"), 114 | "step" => "SECOND" 115 | ], 116 | "keyword" => "" 117 | ]; 118 | $res = $this->query($this->servicesQuery, $variables); 119 | if (!empty($res)) { 120 | $data = json_decode($res, true); 121 | if (count($data['data']['services']) <= 0) { 122 | return false; 123 | } 124 | 125 | $found = false; 126 | foreach ($data['data']['services'] as $service) { 127 | 128 | if ($service['label'] == "skywalking") { 129 | $found = true; 130 | if (!$this->verifyServiceMetrics($service)) { 131 | return false; 132 | } 133 | 134 | $instances = $this->verifyServiceInstances($service); 135 | if ($instances === false) { 136 | return false; 137 | } 138 | } 139 | } 140 | if (!$found) { 141 | return false; 142 | } 143 | return true; 144 | } 145 | 146 | return false; 147 | } 148 | 149 | public function verifyServiceMetrics($service) { 150 | 151 | foreach ($this->allServiceMetrics as $metrics) { 152 | $key = $service['key']; 153 | $label = $service['label']; 154 | $this->info("verifying service ($key:$label), metrics: $metrics"); 155 | 156 | $variables = [ 157 | 'duration' => [ 158 | "start" => date("Y-m-d Hi", $this->startTime), 159 | "end" => date("Y-m-d Hi"), 160 | "step" => "MINUTE" 161 | ], 162 | "id" => $key 163 | ]; 164 | $query = str_replace("{metricsName}", $metrics, $this->metricsQuery); 165 | 166 | $res = $this->query($query, $variables); 167 | if (!empty($res)) { 168 | $data = json_decode($res, true); 169 | if (count($data['data']['metrics']['values']) > 0) { 170 | $check = false; 171 | foreach ($data['data']['metrics']['values'] as $item) { 172 | if ($item['value'] > 0) { 173 | $check = true; 174 | break; 175 | } 176 | } 177 | if (!$check) { 178 | return false; 179 | } 180 | } else { 181 | return false; 182 | } 183 | } else { 184 | return false; 185 | } 186 | } 187 | 188 | return true; 189 | } 190 | 191 | public function verifyServiceInstances($service) { 192 | 193 | $key = $service['key']; 194 | $label = $service['label']; 195 | $this->info("verifying instance ($key:$label)"); 196 | 197 | $variables = [ 198 | 'duration' => [ 199 | "start" => date("Y-m-d His", $this->startTime), 200 | "end" => date("Y-m-d His"), 201 | "step" => "SECOND" 202 | ], 203 | "serviceId" => $key 204 | ]; 205 | 206 | $res = $this->query($this->instanceQuery, $variables); 207 | if (!empty($res)) { 208 | $data = json_decode($res, true); 209 | 210 | if (count($data['data']['instances']) > 0) { 211 | foreach ($data['data']['instances'] as $instance) { 212 | $status = $instance['key'] == '' or $instance['label'] == ''; 213 | if ($status) { 214 | return false; 215 | } else { 216 | foreach ($instance['attributes'] as $attr) { 217 | if ($attr['value'] == '') { 218 | return false; 219 | } 220 | } 221 | } 222 | } 223 | return $data['data']['instances']; 224 | } 225 | return false; 226 | } else { 227 | return false; 228 | } 229 | } 230 | } 231 | 232 | $check = ['verifyServices']; 233 | $e2e = new E2E(); 234 | 235 | foreach($check as $func) { 236 | $e2e->info('php version:' . $argv[1]); 237 | $e2e->info('exec ' . $func); 238 | 239 | $status = false; 240 | for($i = 1; $i <= 10; $i++) { 241 | $e2e->info("test $func $i/10..."); 242 | $status = $e2e->call(); 243 | if (!$status) { 244 | break; 245 | } 246 | sleep(5); 247 | $status = $e2e->$func(); 248 | if ($status === true) { 249 | $status = true; 250 | break; 251 | } 252 | sleep(10); 253 | } 254 | 255 | if (!$status) { 256 | $e2e->info("test $func fail..."); 257 | echo(file_get_contents("/var/log/php" . $argv[1] . "-fpm.log")); 258 | system("sudo chmod -R +rwx /var/crash/*"); 259 | exit(2); 260 | } 261 | 262 | $e2e->info("test $func success..."); 263 | } 264 | -------------------------------------------------------------------------------- /e2e/index.php: -------------------------------------------------------------------------------- 1 | addServer('127.0.0.1', 11211); 22 | 23 | $memcached->setOption(Memcached::OPT_COMPRESSION, false); 24 | //配置存储不压缩,压缩value不利于递增递减 25 | 26 | $memcached->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true); 27 | 28 | $memcached->addServers(array( //添加多台服务器分布式 29 | array('127.0.0.1', 11211, 20), 30 | array('127.0.0.1', 11211, 20), 31 | )); 32 | 33 | $memcached->flush(1); //1秒内清除所有元素 34 | 35 | $memcached->set('name', '2333'); 36 | 37 | $memcached->setByKey('server_master_db', 'mage', '28'); 38 | # 指定 server_key server_master_db 存储键mage 39 | 40 | $memcached->setMulti(array('salary' => '3000', 'email' => '2333')); 41 | // 存储多个元素 42 | 43 | $memcached->setMultiByKey('server_master_db', 44 | array('salary' => '3000', 'email' => '2333') 45 | ); 46 | // 'server_master_db'服务器 存储多个元素 47 | 48 | $memcached->add('name', 'TK'); // 键name不存在添加value 否则添加失败 49 | 50 | $memcached->addByKey('server_master_db', 'mname', 'MTK'); 51 | 52 | $memcached->append('key', '-816'); // 键key的value后追加字符串 -816 53 | 54 | $memcached->appendByKey('server_master_db', 'mname', '-923'); 55 | 56 | $memcached->prepend('name', 'pre-'); #向一个已存在的元素前面追加数据 57 | 58 | $memcached->prependByKey('server_master_db', 'name', 'pre-'); 59 | # 使用server_key自由的将key映射到指定服务器 向一个已存在的元素前面追加数据 60 | 61 | $memcached->get('name'); 62 | 63 | 64 | $memcached->getByKey('server_master_db', 'mname'); # 从特定的服务器检索元素 65 | 66 | $memcached->getAllKeys(); // bug 我一致返回是false 67 | 68 | $memcached->increment('age', '1'); 69 | #增加数值元素的值 如果元素的值不是数值类型,将其作为0处理 70 | 71 | 72 | $memcached->incrementByKey('server_master_db', 'age', '1'); 73 | # 用于识别储存和读取值的服务器 74 | 75 | $memcached->decrement('age', '1'); 76 | #减少数值元素的值 如果元素的值不是数值类型,将其作为0处理 77 | 78 | $memcached->decrementByKey('server_master_db', 'age', '1'); 79 | # 用于识别储存和读取值的服务器 80 | 81 | $memcached->getDelayed(array('name', 'age'), true, null); 82 | # 请求多个元素, 如果with_cas设置为true,会同时请求每个元素的CAS标记 83 | # 指定一个result callback来替代明确的抓取结果 84 | 85 | $memcached->getDelayedByKey('server_master_db', array('name', 'age'), true, null); 86 | 87 | $memcached->fetch(); 88 | # 搭配 $memcached->getDelayed()使用, 从最后一次请求中抓取下一个结果 89 | 90 | $memcached->fetchAll(); 91 | #抓取最后一次请求的结果集中剩余的所有结果 92 | 93 | $memcached->getMulti(array('name', 'age')); #检索多个元素 94 | 95 | $memcached->getMultiByKey('server_master_db', array('mname', 'mage')); 96 | # 从特定服务器检索多个元素 97 | # 与 $this->memcached->fetchAll() 搭配使用 98 | 99 | $memcached->getOption(Memcached::OPT_COMPRESSION); 100 | # 获取Memcached的选项值 101 | 102 | $memcached->getResultCode(); 103 | # 返回最后一次操作的结果代码 Memcached::RES_NOTSTORED 104 | 105 | $memcached->getResultMessage(); 106 | # 返回最后一次操作的结果描述消息 107 | 108 | $memcached->getServerByKey('server_master_db'); # 获取一个key所映射的服务器信息 109 | 110 | $memcached->getServerList(); # 获取服务器池中的服务器列表 111 | 112 | $memcached->getStats(); # 获取服务器池的统计信息 113 | 114 | $memcached->getVersion(); # 获取服务器池中所有服务器的版本信息 115 | 116 | $memcached->isPersistent(); #判断当前连接是否是长连接 117 | 118 | $memcached->replace('name', 'pre-2333'); 119 | #set()类似,但是如果 服务端不存在key, 操作将失败 120 | 121 | $memcached->replaceByKey('server_master_db', 'name', 'pre-2333'); 122 | #setBykey()类似,但是如果 服务端不存在key, 操作将失败 123 | 124 | $memcached->resetServerList(); //清楚服务器池信息 125 | 126 | $memcached->setOption(Memcached::OPT_PREFIX_KEY, "widgets"); 127 | #设置一个memcached选项 128 | 129 | $memcached->setOptions(array()); 130 | #设置一个memcached选项 131 | 132 | //$memcached->setSaslAuthData('', ''); 133 | 134 | $memcached->touch('name', 10); 135 | #设置键name 10秒后过期(只适用30天之内的秒数) ,30天以后请设置时间戳 136 | 137 | $memcached->touchByKey('server_master_db', 'name', 10); 138 | 139 | $memcached->delete('age', 10); 140 | #10秒(秒数/时间戳)内删除一个元素 这个键已经存在删除队列 141 | #该键对应的get、add、replace命令都不可用,直到删除 142 | 143 | $memcached->deleteByKey('server_master_db', 'age'); 144 | 145 | $memcached->deleteMulti(array('age', 'name')); #传入array删除多个key 146 | 147 | $memcached->deleteMultiByKey('server_master_db', array('age', 'name')); 148 | 149 | $memcached->quit(); # 关闭所有打开的链接 150 | 151 | } 152 | -------------------------------------------------------------------------------- /e2e/tests/mysqli.php: -------------------------------------------------------------------------------- 1 | autocommit(FALSE); 28 | $sql = "INSERT INTO mock (name) VALUES (?)"; 29 | $stmt = $mysqli->prepare($sql); 30 | $stmt->bind_param("s",$val1); 31 | $val1 = 'A'; 32 | $stmt->execute(); 33 | $stmt->close(); 34 | mysqli_commit($mysqli); 35 | 36 | $mysqli->query("DROP TABLE mock"); 37 | mysqli_close($mysqli); 38 | } 39 | -------------------------------------------------------------------------------- /e2e/tests/redis.php: -------------------------------------------------------------------------------- 1 | connect('127.0.0.1', 6379); 21 | $redis->select(1); 22 | 23 | $key = 'skywalking'; 24 | // strings 25 | $redis->append($key, "12131"); 26 | $redis->decr($key); 27 | $redis->decr($key, 10); 28 | $redis->decrBy($key, 10); 29 | $redis->get($key); 30 | $redis->getRange($key, 0, 1); 31 | $redis->getSet($key, "11221122"); 32 | $redis->incr($key); 33 | $redis->incr($key, 10); 34 | $redis->incrBy($key, 10); 35 | $redis->mGet([$key, "key1"]); 36 | $redis->mSet([$key => "1818181", "key1" => "8888"]); 37 | $redis->mSetNx([$key => "1818181", "key1" => "8888"]); 38 | $redis->pSetEx($key, 100, 'value'); 39 | $redis->set($key, "11"); 40 | $redis->set($key, "11", 10); 41 | $redis->set($key, "11", ["xx", "ex" => 10]); 42 | $redis->setEx($key, 3600, 'value'); 43 | $redis->setNx($key, 'value'); 44 | $redis->setRange($key, 6, "redis"); 45 | $redis->strlen($key); 46 | 47 | // multiple keys 48 | $redis->mget([$key .'_1', $key . '_2', $key . '_3']); 49 | $redis->getMultiple([$key .'_1', $key . '_2', $key . '_3']); 50 | 51 | // multiple key-value 52 | $redis->mset([$key . '_1' => '111', $key . '_2' => '222', $key . '_3' => '333']); 53 | $redis->msetnx([$key . '_1' => '111', $key . '_2' => '222', $key . '_3' => '333']); 54 | 55 | // uncertain keys 56 | $redis->eval('return {1,2,3};'); 57 | $redis->eval('return {1,2,3};', ['val_01', 'val_02']); 58 | $redis->eval('return {1,2,3};', [$key . '_01', $key . '_02', 'val_01', 'val_02'], 2); 59 | $redis->del($key); 60 | $redis->del($key, $key . '_1'); 61 | $redis->del([$key, $key . '_1', $key . '_2']); 62 | $redis->delete($key); 63 | $redis->unlink($key); 64 | $redis->exists($key); 65 | 66 | // empty commands 67 | $redis->ping(); 68 | $redis->pipeline(); 69 | $redis->set($key, '1'); 70 | $redis->set($key . '_1', '2'); 71 | $redis->set($key . '_2', '3'); 72 | $redis->exec(); 73 | 74 | // expire 75 | $redis->expire($key, 3600); 76 | $redis->expireAt($key, time() + 3600); 77 | $redis->pExpireAt($key, time() + 3600); 78 | $redis->setTimeout($key, 3600); 79 | 80 | // sets 81 | $redis->sAdd($key, "member1"); 82 | $redis->sAdd($key, "member2", "member3"); 83 | } 84 | -------------------------------------------------------------------------------- /e2e/tests/yar.php: -------------------------------------------------------------------------------- 1 | = 4 63 | # define PHP_SKYWALKING_API __attribute__ ((visibility("default"))) 64 | #else 65 | # define PHP_SKYWALKING_API 66 | #endif 67 | 68 | #ifdef ZTS 69 | #include "TSRM.h" 70 | #endif 71 | 72 | #ifndef HOST_NAME_MAX 73 | #if defined(__APPLE__) 74 | #define HOST_NAME_MAX 255 75 | #else 76 | #define HOST_NAME_MAX 64 77 | #endif /* __APPLE__ */ 78 | #endif /* HOST_NAME_MAX */ 79 | 80 | PHP_FUNCTION (skywalking_trace_id); 81 | 82 | PHP_FUNCTION (skywalking_log); 83 | 84 | PHP_FUNCTION (skywalking_tag); 85 | 86 | PHP_MINIT_FUNCTION (skywalking); 87 | 88 | PHP_MSHUTDOWN_FUNCTION (skywalking); 89 | 90 | PHP_RINIT_FUNCTION (skywalking); 91 | 92 | PHP_RSHUTDOWN_FUNCTION (skywalking); 93 | 94 | PHP_MINFO_FUNCTION (skywalking); 95 | 96 | ZEND_BEGIN_MODULE_GLOBALS(skywalking) 97 | zend_bool enable; 98 | 99 | char *service; 100 | char *service_instance; 101 | char *real_service_instance; 102 | 103 | char *oap_version; 104 | char *oap_cross_process_protocol; 105 | char *oap_authentication; 106 | 107 | // tls 108 | char *grpc_address; 109 | zend_bool grpc_tls_enable; 110 | char *grpc_tls_pem_root_certs; 111 | char *grpc_tls_pem_private_key; 112 | char *grpc_tls_pem_cert_chain; 113 | 114 | // log 115 | char *log_level; 116 | char *log_path; 117 | 118 | // cURL 119 | zend_bool curl_response_enable; 120 | zval curl_cache; 121 | 122 | // php error log 123 | zend_bool error_handler_enable; 124 | 125 | // rate limit 126 | void *rate_limiter; 127 | int sample_n_per_3_secs; 128 | 129 | // queue name unique 130 | zend_bool mq_unique; 131 | 132 | HashTable *segments; 133 | zend_bool is_swoole; 134 | 135 | ZEND_END_MODULE_GLOBALS(skywalking) 136 | 137 | extern ZEND_DECLARE_MODULE_GLOBALS(skywalking); 138 | 139 | #ifdef ZTS 140 | #define SKYWALKING_G(v) TSRMG(skywalking_globals_id, zend_skywalking_globals *, v) 141 | #else 142 | #define SKYWALKING_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(skywalking, v) 143 | #endif 144 | 145 | # if defined(ZTS) && defined(COMPILE_DL_SKYWALKING) 146 | ZEND_TSRMLS_CACHE_EXTERN() 147 | # endif 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 SkyAPM 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | [toolchain] 16 | channel = "1.57.0" 17 | components = ["rustfmt", "clippy"] 18 | -------------------------------------------------------------------------------- /scripts/generate-protocol.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # 4 | # Copyright 2021 SkyAPM 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | set -e 20 | 21 | export BASEDIR=$(dirname "$0")/.. 22 | export TEMP_DIR="$BASEDIR"/temp 23 | export PROTOCOL_DIR="$BASEDIR"/src/protocol 24 | export COLLECT_DIR="$BASEDIR"/src/collect 25 | 26 | if [[ ! -d "$TEMP_DIR" ]]; then 27 | mkdir "$TEMP_DIR" 28 | else 29 | rm -rf "$TEMP_DIR"/* 30 | fi 31 | 32 | protoc --proto_path="$PROTOCOL_DIR" --go_out="$TEMP_DIR" --go-grpc_out="$TEMP_DIR" "$PROTOCOL_DIR"/*/*.proto "$PROTOCOL_DIR"/*/*/*.proto 33 | rm -fr "$COLLECT_DIR" 34 | mv "$TEMP_DIR"/skywalking.apache.org/repo/goapi/collect "$BASEDIR"/src/ 35 | rm -fr "$TEMP_DIR" 36 | 37 | # fix 38 | SED_REP='s:skywalking.apache.org/repo/goapi:github.com/SkyAPM/SkyAPM-php-sdk/src:g' 39 | if uname -s | grep Darwin; then 40 | find "$COLLECT_DIR" -type f -name "*.go" | xargs sed -i '' $SED_REP 41 | elif uname -s | grep Linux; then 42 | find "$COLLECT_DIR" -type f -name "*.go" | xargs sed -i $SED_REP 43 | fi 44 | find "$COLLECT_DIR" -name "*Compat.pb.go" -exec rm {} \; 45 | find "$COLLECT_DIR" -name "*Compat_grpc.pb.go" -exec rm {} \; -------------------------------------------------------------------------------- /scripts/pecl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright 2021 SkyAPM 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | pecl package -------------------------------------------------------------------------------- /scripts/version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright 2021 SkyAPM 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | VERSION=5.0.1 19 | OS=`uname` 20 | 21 | echo "OS: $OS" 22 | echo "version: $VERSION" 23 | 24 | if [ "$OS" = 'Darwin' ]; then 25 | sed -i '' "s/\"[0-9].[0-9].[0-9]\"/\"$VERSION\"/" php_skywalking.h 26 | sed -i '' "s/v[0-9].[0-9].[0-9].tar.gz/v$VERSION.tar.gz/g" docs/BUILDING.md 27 | sed -i '' "s/k-[0-9].[0-9].[0-9]/k-$VERSION/" docs/BUILDING.md 28 | fi -------------------------------------------------------------------------------- /skywalking.php: -------------------------------------------------------------------------------- 1 | parameters = $parameters; 24 | } 25 | } 26 | 27 | abstract class AbstractConnection { 28 | protected $parameters; 29 | 30 | public function __construct($parameters) { 31 | $this->parameters = $parameters; 32 | } 33 | } 34 | class StreamConnection extends AbstractConnection { 35 | public function __construct($parameters) { 36 | parent::__construct(new Parameters($parameters)); 37 | } 38 | } 39 | } 40 | 41 | namespace Predis\Command { 42 | interface CommandInterface { 43 | public function getId(); 44 | public function getArguments(); 45 | } 46 | 47 | class TestCommand implements CommandInterface { 48 | public $commandID; 49 | public $arguments; 50 | public function __construct($commandID, $arguments) { 51 | $this->commandID = $commandID; 52 | $this->arguments = $arguments; 53 | } 54 | 55 | public function getId() { 56 | return $this->commandID; 57 | } 58 | 59 | public function getArguments() { 60 | return $this->arguments; 61 | } 62 | } 63 | } 64 | 65 | namespace Predis { 66 | class Client { 67 | 68 | protected $connection; 69 | 70 | public function __construct($parameters = null) { 71 | $this->connection = new \Predis\Connection\StreamConnection($parameters); 72 | } 73 | 74 | public function __call($commandID, $arguments) { 75 | return $this->executeCommand(new \Predis\Command\TestCommand($commandID, $arguments)); 76 | } 77 | 78 | public function executeCommand(\Predis\Command\CommandInterface $command) { 79 | 80 | } 81 | } 82 | } 83 | 84 | namespace Grpc { 85 | class BaseStub { 86 | private $hostname; 87 | private $hostname_override; 88 | 89 | public function __construct($hostname) { 90 | $this->hostname = $hostname; 91 | } 92 | 93 | public function _simpleRequest($method) {} 94 | } 95 | 96 | class HelloClient extends BaseStub { 97 | 98 | public function __construct($hostname) { 99 | parent::__construct($hostname); 100 | } 101 | 102 | public function hello() { 103 | $this->_simpleRequest("user.mock"); 104 | } 105 | } 106 | } 107 | 108 | namespace PhpAmqpLib\Connection { 109 | 110 | class AbstractConnection { 111 | protected $construct_params; 112 | } 113 | class AMQPStreamConnection extends AbstractConnection { 114 | 115 | 116 | public function __construct($host, $port) { 117 | $this->construct_params = func_get_args(); 118 | } 119 | } 120 | } 121 | 122 | namespace PhpAmqpLib\Channel { 123 | class AbstractChannel { 124 | protected $connection; 125 | public function __construct($connection) { 126 | $this->connection = $connection; 127 | } 128 | } 129 | class AMQPChannel extends AbstractChannel { 130 | 131 | public function __construct($connection, $channel_id = null, $auto_decode = true, $channel_rpc_timeout = 0) { 132 | parent::__construct($connection); 133 | } 134 | 135 | public function basic_publish($msg, $exchange = '') { 136 | } 137 | 138 | } 139 | } 140 | 141 | namespace { 142 | $channel = new \PhpAmqpLib\Channel\AMQPChannel(new \PhpAmqpLib\Connection\AMQPStreamConnection("127.0.0.1", 2222)); 143 | $channel->basic_publish("test", "exchange"); 144 | $client = new \Predis\Client(["host" => "127.0.0.1", "port" => 6379]); 145 | $client->set('foo', 'bar'); 146 | $client->get('foo'); 147 | 148 | // test grpc 149 | $hello = new \Grpc\HelloClient("127.0.0.1:8888"); 150 | $hello->hello(); 151 | var_dump(skywalking_trace_id()); 152 | 153 | skywalking_tag("test", "foo", "bar"); 154 | skywalking_log("test", 'info', 'skywalking custom log function skywalking_log(string $key, string $msg[, bool $is_error])', false); 155 | // 156 | // // test pdo 157 | // $dbh = new \PDO("mysql:host=127.0.0.1;port=3306;dbname=mock", "root", "111111"); 158 | // $dbh->exec("SET names utf8"); 159 | // $dbh->query("select * from mock"); 160 | // $dbh->prepare("select * from mock where id = ?"); 161 | // 162 | // $dbh->beginTransaction(); 163 | // $dbh->query("select * from mock"); 164 | // $dbh->commit(); 165 | 166 | // test curl 167 | // $ch = curl_init("https://api.github.com/repos"); 168 | // curl_setopt($ch, 9923, []); 169 | // curl_exec($ch); 170 | // $ch = curl_init("https://api.github.com/repos"); 171 | // curl_exec($ch); 172 | } 173 | ?> 174 | -------------------------------------------------------------------------------- /src/reporter/ipc.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 SkyAPM 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | 16 | use anyhow::{anyhow, bail, Context}; 17 | use ipc_channel::ipc::{bytes_channel, IpcBytesReceiver, IpcBytesSender, IpcSharedMemory}; 18 | use std::{ 19 | mem::{size_of, transmute}, 20 | sync::{ 21 | atomic::{AtomicUsize, Ordering}, 22 | Mutex, 23 | }, 24 | }; 25 | use tokio::sync::OnceCell; 26 | 27 | const MAX_MESSAGE_QUEUE_COUNT: usize = 4096; 28 | 29 | static MESSAGE_QUEUE_SENDER: OnceCell> = OnceCell::const_new(); 30 | static MESSAGE_QUEUE_RECEIVER: OnceCell> = OnceCell::const_new(); 31 | static MESSAGE_QUEUE_COUNT: OnceCell = OnceCell::const_new(); 32 | 33 | pub fn init() -> anyhow::Result<()> { 34 | // init count 35 | let count: [u8; size_of::()] = unsafe { transmute(AtomicUsize::new(0)) }; 36 | MESSAGE_QUEUE_COUNT.set(IpcSharedMemory::from_bytes(&count))?; 37 | 38 | let (sender, receiver) = bytes_channel()?; 39 | MESSAGE_QUEUE_SENDER.set(Mutex::new(sender))?; 40 | MESSAGE_QUEUE_RECEIVER.set(Mutex::new(receiver))?; 41 | 42 | Ok(()) 43 | } 44 | 45 | pub fn send(data: &[u8]) -> anyhow::Result<()> { 46 | 47 | let old_count = get_message_queue_count()?.fetch_add(1, Ordering::SeqCst); 48 | 49 | log::debug!("ipc::send current ipc have {} items", old_count); 50 | if old_count >= MAX_MESSAGE_QUEUE_COUNT { 51 | get_message_queue_count()?.fetch_min(MAX_MESSAGE_QUEUE_COUNT, Ordering::SeqCst); 52 | bail!("message queue is fulled"); 53 | } 54 | 55 | let lock = MESSAGE_QUEUE_SENDER 56 | .get() 57 | .context("message queue sender: channel hasn't initialized or failed")? 58 | .try_lock() 59 | .map_err(|e| anyhow!("message queue sender is locked: {:?}", e))?; 60 | lock.send(data)?; 61 | Ok(()) 62 | } 63 | 64 | pub fn receive() -> anyhow::Result> { 65 | let lock = MESSAGE_QUEUE_RECEIVER 66 | .get() 67 | .context("message queue receiver: channel hasn't initialized or failed")? 68 | .lock() 69 | .map_err(|e| anyhow!("message queue receiver get lock failed: {:?}", e))?; 70 | let buffer = lock 71 | .recv() 72 | .map_err(|e| anyhow!("message queue receive failed: {:?}", e))?; 73 | 74 | get_message_queue_count()?.fetch_sub(1, Ordering::SeqCst); 75 | 76 | Ok(buffer) 77 | } 78 | 79 | fn get_message_queue_count<'a>() -> anyhow::Result<&'a AtomicUsize> { 80 | let count = MESSAGE_QUEUE_COUNT 81 | .get() 82 | .context("message queue count: channel hasn't initialized or failed")? 83 | .as_ptr() as *const AtomicUsize; 84 | unsafe { count.as_ref().context("why message queue count is null") } 85 | } -------------------------------------------------------------------------------- /src/reporter/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 SkyAPM 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | pub mod grpc; 16 | pub mod ipc; -------------------------------------------------------------------------------- /src/sky_base.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_SKY_BASE_H 20 | #define SKYWALKING_SKY_BASE_H 21 | 22 | #include "pthread.h" 23 | 24 | #ifdef __cplusplus 25 | #define SKY_BEGIN_EXTERN_C() extern "C" { 26 | #define SKY_END_EXTERN_C() } 27 | #else 28 | #define SKY_BEGIN_EXTERN_C() 29 | #define SKY_END_EXTERN_C() 30 | #endif 31 | 32 | typedef struct { 33 | pthread_mutex_t lock; 34 | pthread_mutexattr_t lock_attr; 35 | char service[1024]; 36 | char serviceInstance[1024]; 37 | int id; 38 | } mutex_service_t; 39 | 40 | typedef mutex_service_t mutex_service; 41 | 42 | 43 | #endif //SKYWALKING_SKY_BASE_H 44 | -------------------------------------------------------------------------------- /src/sky_core_cross_process.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #include "sky_core_cross_process.h" 20 | #include "php.h" 21 | #include 22 | #include 23 | #include 24 | 25 | #include "sky_util_base64.h" 26 | 27 | sky_core_cross_process_t *sky_core_cross_process_new(char *header) { 28 | sky_core_cross_process_t *cross_process = (sky_core_cross_process_t *) emalloc(sizeof(sky_core_cross_process_t)); 29 | memset(cross_process, 0, sizeof(sky_core_cross_process_t)); 30 | 31 | if (header != NULL) { 32 | char **bag = (char **) malloc(8); 33 | char *p = strtok(header, "-"); 34 | int i = 0; 35 | while (p != NULL) { 36 | asprintf(&bag[i], "%s", p); 37 | i++; 38 | p = strtok(NULL, "-"); 39 | } 40 | 41 | if (i >= 8) { 42 | cross_process->sample = (int) strtol(bag[0], NULL, 10); 43 | cross_process->traceId = sky_util_base64_decode(bag[1]); 44 | cross_process->parentSegmentId = sky_util_base64_decode(bag[2]); 45 | cross_process->parentSpanId = (int) strtol(bag[3], NULL, 10); 46 | cross_process->parentService = sky_util_base64_decode(bag[4]); 47 | cross_process->parentServiceInstance = sky_util_base64_decode(bag[5]); 48 | cross_process->parentEndpoint = sky_util_base64_decode(bag[6]); 49 | cross_process->networkAddress = sky_util_base64_decode(bag[7]); 50 | } 51 | } 52 | 53 | return cross_process; 54 | } 55 | 56 | void sky_core_cross_process_set_trace_id(sky_core_cross_process_t *cross_process, char *trace_id) { 57 | if (cross_process->traceId == NULL) { 58 | cross_process->traceId = (char *) emalloc(strlen(trace_id) + 1); 59 | bzero(cross_process->traceId, strlen(trace_id) + 1); 60 | memcpy(cross_process->traceId, trace_id, strlen(trace_id)); 61 | } 62 | } 63 | 64 | //std::string SkyCoreCrossProcess::encode(int spanId, const std::string &peer) { 65 | // 66 | // std::vector tmp; 67 | // tmp.emplace_back("1"); 68 | // tmp.emplace_back(Base64::encode(traceId)); 69 | // tmp.emplace_back(Base64::encode(_segmentId)); 70 | // tmp.emplace_back(std::to_string(spanId)); 71 | // tmp.emplace_back(Base64::encode(_service)); 72 | // tmp.emplace_back(Base64::encode(_serviceInstance)); 73 | // tmp.emplace_back(Base64::encode(_endpoint)); 74 | // tmp.emplace_back(Base64::encode(peer)); 75 | // 76 | // std::string header; 77 | // 78 | // for (const auto &val: tmp) { 79 | // header.append(val); 80 | // header.append("-"); 81 | // } 82 | // 83 | // header.erase(header.end() - 1); 84 | // 85 | // return header; 86 | //} 87 | // 88 | //void SkyCoreCrossProcess::setService(const std::string &service) { 89 | // _service = service; 90 | //} 91 | // 92 | //void SkyCoreCrossProcess::setServiceInstance(const std::string &serviceInstance) { 93 | // _serviceInstance = serviceInstance; 94 | //} 95 | // 96 | //void SkyCoreCrossProcess::setSegmentId(const std::string &segmentId) { 97 | // _segmentId = segmentId; 98 | //} 99 | // 100 | //void SkyCoreCrossProcess::setEndpoint(const std::string &endpoint) { 101 | // _endpoint = endpoint; 102 | //} 103 | // 104 | //const std::string &SkyCoreCrossProcess::getTraceId() { 105 | // return traceId; 106 | //} 107 | // 108 | //const std::string &SkyCoreCrossProcess::getParentTraceSegmentId() { 109 | // return parentSegmentId; 110 | //} 111 | // 112 | //int SkyCoreCrossProcess::getParentSpanId() const { 113 | // return parentSpanId; 114 | //} 115 | // 116 | //const std::string &SkyCoreCrossProcess::getParentService() { 117 | // return parentService; 118 | //} 119 | // 120 | //const std::string &SkyCoreCrossProcess::getParentServiceInstance() { 121 | // return parentServiceInstance; 122 | //} 123 | // 124 | //const std::string &SkyCoreCrossProcess::getParentEndpoint() { 125 | // return parentEndpoint; 126 | //} 127 | // 128 | //const std::string &SkyCoreCrossProcess::getNetworkAddress() { 129 | // return networkAddress; 130 | //} -------------------------------------------------------------------------------- /src/sky_core_cross_process.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | 20 | #ifndef SKYWALKING_SKY_CORE_CROSS_PROCESS_H 21 | #define SKYWALKING_SKY_CORE_CROSS_PROCESS_H 22 | 23 | typedef struct sky_core_cross_process_t { 24 | 25 | // https://github.com/apache/skywalking/blob/master/docs/en/protocols/Skywalking-Cross-Process-Propagation-Headers-Protocol-v3.md 26 | int sample; 27 | char *traceId; 28 | char *parentSegmentId; 29 | int parentSpanId; 30 | char *parentService; 31 | char *parentServiceInstance; 32 | char *parentEndpoint; 33 | char *networkAddress; 34 | } sky_core_cross_process_t; 35 | 36 | sky_core_cross_process_t *sky_core_cross_process_new(char *header); 37 | 38 | void sky_core_cross_process_set_trace_id(sky_core_cross_process_t *cross_process, char *trace_id); 39 | 40 | //#include 41 | // 42 | //class SkyCoreCrossProcess { 43 | //public: 44 | // SkyCoreCrossProcess(const std::string &header, const std::string &segmentId); 45 | // 46 | // std::string encode(int spanId, const std::string &peer); 47 | // 48 | // void setService(const std::string &service); 49 | // 50 | // void setServiceInstance(const std::string &serviceInstance); 51 | // 52 | // void setSegmentId(const std::string &segmentId); 53 | // 54 | // void setEndpoint(const std::string &endpoint); 55 | // 56 | // const std::string &getTraceId(); 57 | // 58 | // const std::string &getParentTraceSegmentId(); 59 | // 60 | // int getParentSpanId() const; 61 | // 62 | // const std::string &getParentService(); 63 | // 64 | // const std::string &getParentServiceInstance(); 65 | // 66 | // const std::string &getParentEndpoint(); 67 | // 68 | // const std::string &getNetworkAddress(); 69 | // 70 | //private: 71 | // std::string _service; 72 | // std::string _serviceInstance; 73 | // std::string _segmentId; 74 | // std::string _endpoint; 75 | // 76 | // // https://github.com/apache/skywalking/blob/master/docs/en/protocols/Skywalking-Cross-Process-Propagation-Headers-Protocol-v3.md 77 | // int sample; 78 | // std::string traceId; 79 | // std::string parentSegmentId; 80 | // int parentSpanId; 81 | // std::string parentService; 82 | // std::string parentServiceInstance; 83 | // std::string parentEndpoint; 84 | // std::string networkAddress; 85 | //}; 86 | 87 | 88 | #endif //SKYWALKING_SKY_CORE_CROSS_PROCESS_H 89 | -------------------------------------------------------------------------------- /src/sky_core_log.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #include "sky_core_log.h" 20 | #include "php.h" 21 | #include 22 | #include "sky_util_php.h" 23 | #include "ext/standard/php_smart_string.h" 24 | 25 | sky_core_log_t *sky_core_log_new() { 26 | sky_core_log_t *log = (sky_core_log_t *) emalloc(sizeof(sky_core_log_t)); 27 | 28 | struct timeval tv; 29 | gettimeofday(&tv, NULL); 30 | log->time = tv.tv_sec * 1000 + tv.tv_usec / 1000; 31 | log->data_total = 4; 32 | log->data_size = 0; 33 | log->data = (sky_core_log_data_t **) emalloc(log->data_total * sizeof(sky_core_log_data_t)); 34 | return log; 35 | } 36 | 37 | void sky_core_log_add_data(sky_core_log_t *log, const char *key, const char *value) { 38 | if (log->data_size == log->data_total - 1) { 39 | sky_core_log_data_t **more = (sky_core_log_data_t **) erealloc(log->data, log->data_total * 2 * sizeof(sky_core_log_data_t)); 40 | if (more != NULL) { 41 | log->data_total *= 2; 42 | log->data = more; 43 | } else { 44 | return; 45 | } 46 | } 47 | 48 | 49 | sky_core_log_data_t *data = (sky_core_log_data_t *) emalloc(sizeof(sky_core_log_data_t)); 50 | data->key = key; 51 | data->value = value; 52 | log->data[log->data_size] = data; 53 | log->data_size++; 54 | } 55 | 56 | void sky_core_log_free(sky_core_log_t *log) { 57 | 58 | } 59 | 60 | char *sky_core_log_to_json(sky_core_log_t *log) { 61 | char *json; 62 | 63 | smart_string data = {0}; 64 | smart_string_appendl(&data, "[", 1); 65 | 66 | for (int i = 0; i < log->data_size; ++i) { 67 | sky_core_log_data_t *log_data = log->data[i]; 68 | char *data_json; 69 | asprintf(&data_json, "{\"key\":\"%s\",\"value\":\"%s\"}", log_data->key, log_data->value); 70 | smart_string_appendl(&data, data_json, strlen(data_json)); 71 | free(data_json); 72 | if (i + 1 < log->data_size) { 73 | smart_string_appendl(&data, ",", 1); 74 | } 75 | } 76 | 77 | smart_string_appendl(&data, "]", 1); 78 | smart_string_0(&data); 79 | 80 | asprintf(&json, "{\"time\":%ld,\"data\":%s}", log->time, data.c); 81 | return json; 82 | } 83 | -------------------------------------------------------------------------------- /src/sky_core_log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_LOG_H 20 | #define SKYWALKING_LOG_H 21 | 22 | typedef struct sky_core_log_data_t { 23 | const char *key; 24 | const char *value; 25 | } sky_core_log_data_t; 26 | 27 | typedef struct sky_core_log_t { 28 | int data_total; 29 | int data_size; 30 | 31 | long time; 32 | sky_core_log_data_t **data; 33 | } sky_core_log_t; 34 | 35 | sky_core_log_t *sky_core_log_new(); 36 | 37 | void sky_core_log_add_data(sky_core_log_t *log, const char *key, const char *value); 38 | 39 | void sky_core_log_free(sky_core_log_t *tag); 40 | 41 | char *sky_core_log_to_json(sky_core_log_t *span); 42 | 43 | // 44 | // 45 | //class SkyCoreLog { 46 | //public: 47 | // SkyCoreLog(std::string key, std::string value); 48 | // 49 | // long getTime(); 50 | // 51 | // const std::string &getKey(); 52 | // 53 | // const std::string &getValue(); 54 | // 55 | //private: 56 | // long _time; 57 | // std::string _key; 58 | // std::string _value; 59 | //}; 60 | 61 | #endif //SKYWALKING_LOG_H 62 | -------------------------------------------------------------------------------- /src/sky_core_module.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include "sky_core_module.h" 22 | #include "php.h" 23 | #include "SAPI.h" 24 | #include "ext/standard/php_var.h" 25 | #include "zend_hash.h" 26 | #include "sys/ipc.h" 27 | #include "pthread.h" 28 | 29 | #include "php_skywalking.h" 30 | #include "sky_core_segment.h" 31 | #include "sky_core_span.h" 32 | #include "sky_core_tag.h" 33 | #include "sky_plugin_curl.h" 34 | #include "sky_core_report.h" 35 | #include "sky_plugin_redis.h" 36 | #include "sys/mman.h" 37 | 38 | void *thread_sky_core_report_new(void *argv) { 39 | // report_new_t *args = (report_new_t *) argv; 40 | sky_core_report_new( 41 | SKYWALKING_G(grpc_address), 42 | SKYWALKING_G(service), 43 | SKYWALKING_G(real_service_instance), 44 | SKYWALKING_G(log_level), 45 | SKYWALKING_G(log_path) 46 | ); 47 | } 48 | 49 | void delete_segments(zval *zv) { 50 | sky_core_segment_t *t = Z_PTR_P(zv); 51 | efree(t); 52 | } 53 | 54 | int sky_core_module_init(INIT_FUNC_ARGS) { 55 | 56 | if (strlen(SKYWALKING_G(service_instance)) == 0) { 57 | char *instance = sky_core_service_instance_id(); 58 | char *service_instance = (char *) pemalloc(strlen(instance), 1); 59 | memcpy(service_instance, instance, strlen(instance)); 60 | SKYWALKING_G(real_service_instance) = service_instance; 61 | } 62 | 63 | // todo if on 64 | if (1 == 1) { 65 | sky_plugin_redis_hooks(); 66 | } 67 | 68 | // todo if on 69 | if (1 == 1) { 70 | sky_plugin_curl_hooks(); 71 | } 72 | 73 | SKYWALKING_G(segments) = pemalloc(sizeof(HashTable), 1); 74 | zend_hash_init(SKYWALKING_G(segments), 0, NULL, delete_segments, 1); 75 | 76 | if (sky_core_report_ipc_init()) { 77 | // register 78 | pid_t pid = fork(); 79 | if (pid < 0) { 80 | fprintf(stderr, "fork failed"); 81 | } else if (pid == 0) { 82 | prctl(PR_SET_PDEATHSIG, SIGTERM); 83 | thread_sky_core_report_new(NULL); 84 | exit(0); 85 | } 86 | } 87 | return 0; 88 | } 89 | 90 | static ZEND_RSRC_DTOR_FUNC(skywalking_dtor) { 91 | 92 | }; 93 | 94 | void sky_core_module_free() { 95 | pefree(SKYWALKING_G(segments), 1); 96 | } 97 | 98 | void sky_core_request_init(zval *request, u_int64_t request_id) { 99 | if (strncmp(sapi_module.name, "fpm-fcgi", sizeof("fpm-fcgi") - 1) != 0) { 100 | return; 101 | } 102 | 103 | array_init(&SKYWALKING_G(curl_cache)); 104 | 105 | zval *_server = NULL; 106 | zval *cross_process_protocol = NULL; 107 | char *operation_name = NULL; 108 | char *peer = NULL; 109 | 110 | if (request != NULL) { 111 | // todo 112 | } else { // fpm or cli mode 113 | zend_bool jit = PG(auto_globals_jit); 114 | if (jit) { 115 | zend_string *server = zend_string_init(ZEND_STRL("_SERVER"), 0); 116 | zend_is_auto_global(server); 117 | zend_string_release(server); 118 | } 119 | _server = zend_hash_str_find(&EG(symbol_table), ZEND_STRL("_SERVER")); 120 | if (strcasecmp(SKYWALKING_G(oap_cross_process_protocol), "3.0") == 0) { 121 | cross_process_protocol = zend_hash_str_find(Z_ARRVAL_P(_server), ZEND_STRL("HTTP_SW8")); 122 | } 123 | 124 | // name 125 | if (strcasecmp("cli", sapi_module.name) == 0) { 126 | asprintf(&operation_name, "%s", "cli"); 127 | } else { 128 | zval *request_uri = zend_hash_str_find(Z_ARRVAL_P(_server), ZEND_STRL("REQUEST_URI")); 129 | asprintf(&operation_name, "%s", Z_STRVAL_P(request_uri)); 130 | } 131 | 132 | // peer 133 | zval *http_host = zend_hash_str_find(Z_ARRVAL_P(_server), ZEND_STRL("HTTP_HOST")); 134 | zval *server_port = zend_hash_str_find(Z_ARRVAL_P(_server), ZEND_STRL("SERVER_PORT")); 135 | if (http_host == NULL) { 136 | http_host = zend_hash_str_find(Z_ARRVAL_P(_server), ZEND_STRL("SERVER_ADDR")); 137 | } 138 | if (http_host != NULL && server_port != NULL) { 139 | asprintf(&peer, "%s:%s", Z_STRVAL_P(http_host), Z_STRVAL_P(server_port)); 140 | } 141 | } 142 | 143 | // new segment 144 | char *protocol = cross_process_protocol != NULL ? Z_STRVAL_P(cross_process_protocol) : NULL; 145 | sky_core_segment_t *core_segment = sky_core_segment_new(protocol); 146 | sky_core_span_t *span = sky_core_span_new(Entry, Http, 8001); 147 | sky_core_span_set_operation_name(span, operation_name); 148 | sky_core_span_set_peer(span, peer); 149 | 150 | sky_core_span_add_tag(span, sky_core_tag_new("url", operation_name)); 151 | 152 | zval *request_method = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), 153 | ZEND_STRL("REQUEST_METHOD")); 154 | if (request_method != NULL) { 155 | sky_core_span_add_tag(span, sky_core_tag_new("http.method", Z_STRVAL_P(request_method))); 156 | } 157 | 158 | sky_core_segment_add_span(core_segment, span); 159 | 160 | zend_hash_index_add_ptr(SKYWALKING_G(segments), request_id, core_segment); 161 | } 162 | 163 | void sky_core_request_free(zval *response, u_int64_t request_id) { 164 | if (strncmp(sapi_module.name, "fpm-fcgi", sizeof("fpm-fcgi") - 1) != 0) { 165 | return; 166 | } 167 | zval_dtor(&SKYWALKING_G(curl_cache)); 168 | 169 | if (SKYWALKING_G(segments) == NULL) { 170 | return; 171 | } 172 | 173 | sky_core_segment_t *core_segment = (sky_core_segment_t *) zend_hash_index_find_ptr(SKYWALKING_G(segments), 174 | request_id); 175 | 176 | if (response == NULL) { 177 | // segment->setStatusCode(SG(sapi_headers).http_response_code); 178 | } 179 | sky_core_span_set_end_time(core_segment->spans[0]); 180 | 181 | 182 | // zend_string *persistent_id = zend_string_init(skywalking_persistent_id, strlen(skywalking_persistent_id), 0); 183 | // zend_resource *le = zend_hash_find_ptr(&EG(persistent_list), persistent_id); 184 | // zend_string_release(persistent_id); 185 | // sky_core_report_t *report = (sky_core_report_t *) le->ptr; 186 | sky_core_segment_set_service(core_segment, SKYWALKING_G(service)); 187 | sky_core_segment_set_service_instance(core_segment, SKYWALKING_G(real_service_instance)); 188 | 189 | char *json = NULL; 190 | sky_core_segment_to_json(&json, core_segment); 191 | efree(json); 192 | sky_core_report_ipc_send(json, strlen(json)); 193 | // sky_core_report_push(report, json); 194 | 195 | zend_hash_index_del(SKYWALKING_G(segments), request_id); 196 | // efree(segment); 197 | } 198 | -------------------------------------------------------------------------------- /src/sky_core_module.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef SKYWALKING_SKY_CORE_MODULE_H 19 | #define SKYWALKING_SKY_CORE_MODULE_H 20 | 21 | #include "php.h" 22 | #include "pthread.h" 23 | 24 | #define SKY_FIND_FUNC(name) zend_hash_str_find_ptr(CG(function_table), name, sizeof(name) - 1) 25 | 26 | typedef struct skywalking_t { 27 | char service[1024]; 28 | char serviceInstance[1024]; 29 | char *connect; 30 | } skywalking_t; 31 | 32 | int sky_core_module_init(INIT_FUNC_ARGS); 33 | 34 | static ZEND_RSRC_DTOR_FUNC(skywalking_dtor); 35 | 36 | void sky_core_module_free(); 37 | 38 | void sky_core_request_init(zval *request, u_int64_t request_id); 39 | 40 | void sky_core_request_free(zval *response, u_int64_t request_id); 41 | 42 | #endif //SKYWALKING_SKY_CORE_MODULE_H 43 | -------------------------------------------------------------------------------- /src/sky_core_report.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef SKYWALKING_SKY_CORE_REPORT_H 19 | #define SKYWALKING_SKY_CORE_REPORT_H 20 | 21 | typedef struct sky_core_report_t { 22 | char *address; 23 | char *service; 24 | char *service_instance; 25 | } sky_core_report_t; 26 | 27 | bool sky_core_report_ipc_init(); 28 | 29 | bool sky_core_report_ipc_send(char *data, size_t len); 30 | 31 | bool sky_core_report_new(char *address, char *service, char *service_instance, char *log_level, char *log_path); 32 | 33 | char *sky_core_report_trace_id(); 34 | 35 | char *sky_core_service_instance_id(); 36 | 37 | #endif //SKYWALKING_SKY_CORE_REPORT_H 38 | -------------------------------------------------------------------------------- /src/sky_core_report.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 SkyAPM 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | #[macro_use] 16 | extern crate log; 17 | extern crate simplelog; 18 | 19 | use std::os::raw::{c_char, c_void}; 20 | use std::boxed::Box; 21 | use std::cmp::max; 22 | use std::ffi::{CStr, CString}; 23 | use reporter::grpc::Reporter; 24 | use reporter::{grpc, ipc}; 25 | use tokio; 26 | use local_ip_address::local_ip; 27 | use uuid::Uuid; 28 | use std::process; 29 | use rand::Rng; 30 | use rand; 31 | use std::thread; 32 | use std::ptr::null_mut; 33 | use std::{ 34 | slice::from_raw_parts, 35 | }; 36 | 37 | pub mod skywalking_proto { 38 | pub mod v3 { 39 | tonic::include_proto!("skywalking.v3"); 40 | } 41 | } 42 | 43 | pub mod reporter; 44 | 45 | #[no_mangle] 46 | extern "C" fn sky_core_report_ipc_init() -> bool { 47 | return match ipc::init() { 48 | Ok(_) => { 49 | log::debug!("sky_core_report_ipc_init ok"); 50 | true 51 | } 52 | Err(e) => { 53 | log::error!("sky_core_report_ipc_init err {}", e.to_string()); 54 | false 55 | } 56 | }; 57 | } 58 | 59 | #[no_mangle] 60 | extern "C" fn sky_core_report_ipc_send(data: *const c_char, len: usize) -> bool { 61 | let data = unsafe { from_raw_parts(data.cast(), len) }; 62 | return match ipc::send(data) { 63 | Ok(_) => { 64 | log::debug!("sky_core_report_ipc_send ok"); 65 | true 66 | } 67 | Err(e) => { 68 | log::error!("sky_core_report_ipc_send err {}", e.to_string()); 69 | false 70 | } 71 | }; 72 | } 73 | 74 | #[no_mangle] 75 | extern "C" fn sky_core_report_trace_id() -> *const c_char { 76 | let mut rng: i32 = rand::thread_rng().gen_range(100000..999999); 77 | let mut trace_id = format!("{}.{}.{}", Uuid::new_v4().to_string(), process::id().to_string(), rng.to_string()); 78 | trace_id = trace_id.replace("-", ""); 79 | return CString::new(trace_id).expect("").into_raw(); 80 | } 81 | 82 | 83 | #[no_mangle] 84 | extern "C" fn sky_core_service_instance_id() -> *const c_char { 85 | let service_instance = Uuid::new_v4().to_string() + "@" + &local_ip().unwrap().to_string(); 86 | return CString::new(service_instance).expect("").into_raw(); 87 | } 88 | 89 | #[no_mangle] 90 | extern "C" fn sky_core_report_new( 91 | address: *const c_char, 92 | service: *const c_char, 93 | service_instance: *const c_char, 94 | log_level: *const c_char, 95 | log_path: *const c_char, 96 | ) -> bool { 97 | let f = || unsafe { 98 | let address = CStr::from_ptr(address).to_str()?; 99 | let service = CStr::from_ptr(service).to_str()?; 100 | let service_instance = CStr::from_ptr(service_instance).to_str()?; 101 | let log_level = CStr::from_ptr(log_level).to_str()?; 102 | let log_path = CStr::from_ptr(log_path).to_str()?; 103 | grpc::init( 104 | address.to_string(), 105 | service.to_string(), 106 | service_instance.to_string(), 107 | log_level.to_string(), 108 | log_path.to_string(), 109 | )?; 110 | Ok::<_, anyhow::Error>(()) 111 | }; 112 | match f() { 113 | Ok(_) => true, 114 | Err(e) => false 115 | } 116 | } -------------------------------------------------------------------------------- /src/sky_core_segment.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | 20 | #ifndef SKYWALKING_SKY_CORE_SEGMENT_H 21 | #define SKYWALKING_SKY_CORE_SEGMENT_H 22 | 23 | #include 24 | #include "sky_core_span.h" 25 | #include "sky_core_cross_process.h" 26 | 27 | #define btoa(x) ((x)?"true":"false") 28 | 29 | typedef struct sky_core_segment_t { 30 | bool isSkip; 31 | sky_core_cross_process_t *cross_process; 32 | 33 | int span_total; 34 | int span_size; 35 | 36 | // Tracing.proto 37 | char *traceId; 38 | char *traceSegmentId; 39 | sky_core_span_t **spans; 40 | char *service; 41 | char *serviceInstance; 42 | bool isSizeLimited; 43 | } sky_core_segment_t; 44 | 45 | sky_core_segment_t *sky_core_segment_new(char *protocol); 46 | 47 | void sky_core_segment_add_span(sky_core_segment_t *segment, sky_core_span_t *span); 48 | 49 | void sky_core_segment_set_service(sky_core_segment_t *segment, char *service); 50 | 51 | void sky_core_segment_set_service_instance(sky_core_segment_t *segment, char *instance); 52 | 53 | int sky_core_segment_to_json(char **json, sky_core_segment_t *segment); 54 | 55 | //#include 56 | //#include 57 | //#include "sky_core_cross_process.h" 58 | //#include "sky_core_span.h" 59 | // 60 | //class SkyCoreSegment{ 61 | // public: 62 | // explicit SkyCoreSegment(const std::string &header); 63 | // 64 | // SkyCoreSpan *createSpan(SkyCoreSpanType type, SkyCoreSpanLayer layer, int componentId); 65 | // 66 | // SkyCoreSpan * 67 | // findOrCreateSpan(const std::string &name, SkyCoreSpanType type, SkyCoreSpanLayer layer, int componentId); 68 | // 69 | // SkyCoreSpan *firstSpan(); 70 | // 71 | // std::string marshal(); 72 | // 73 | // void setStatusCode(int code); 74 | // 75 | // std::string createHeader(SkyCoreSpan *span); 76 | // 77 | // void createRefs(); 78 | // 79 | // const std::string &getTraceId(); 80 | // 81 | // void setSkip(bool skip); 82 | // 83 | // bool skip() const; 84 | // 85 | // ~SkyCoreSegment(); 86 | // 87 | // private: 88 | // SkyCoreCrossProcess *cp; 89 | // std::string header; 90 | // bool isSkip; 91 | // 92 | // // Tracing.proto 93 | // std::string traceId; 94 | // std::string traceSegmentId; 95 | // std::vector spans; 96 | // std::string service; 97 | // std::string serviceInstance; 98 | // bool isSizeLimited = false; 99 | //}; 100 | 101 | 102 | #endif //SKYWALKING_SKY_CORE_SEGMENT_H 103 | -------------------------------------------------------------------------------- /src/sky_core_segment_reference.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | 20 | #include "sky_core_segment_reference.h" 21 | #include "php.h" 22 | #include 23 | 24 | sky_core_segment_ref_t *sky_core_segment_ref_new() { 25 | return (sky_core_segment_ref_t *) emalloc(sizeof(sky_core_segment_ref_t)); 26 | } 27 | -------------------------------------------------------------------------------- /src/sky_core_segment_reference.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | 20 | #ifndef SKYWALKING_SKY_CORE_SEGMENT_REFERENCE_H 21 | #define SKYWALKING_SKY_CORE_SEGMENT_REFERENCE_H 22 | 23 | typedef enum sky_core_segment_ref_type { 24 | CrossProcess, CrossThread 25 | } sky_core_segment_ref_type; 26 | 27 | typedef struct sky_core_segment_ref_t { 28 | // Tracing.proto 29 | sky_core_segment_ref_type refType; 30 | char *traceId; 31 | char *parentTraceSegmentId; 32 | int parentSpanId; 33 | char *parentService; 34 | char *parentServiceInstance; 35 | char *parentEndpoint; 36 | char *networkAddressUsedAtPeer; 37 | } sky_core_segment_ref_t; 38 | 39 | sky_core_segment_ref_t * sky_core_segment_ref_new(); 40 | 41 | #endif //SKYWALKING_SKY_CORE_SEGMENT_REFERENCE_H 42 | -------------------------------------------------------------------------------- /src/sky_core_span.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_SKY_CORE_SPAN_H 20 | #define SKYWALKING_SKY_CORE_SPAN_H 21 | 22 | #include 23 | #include "sky_core_tag.h" 24 | #include "sky_core_log.h" 25 | #include "sky_core_segment_reference.h" 26 | 27 | typedef enum sky_core_span_type { 28 | Entry, Exit, Local 29 | } sky_core_span_type; 30 | 31 | typedef enum sky_core_span_layer { 32 | Unknown, 33 | Database, 34 | RPCFramework, 35 | Http, 36 | MQ, 37 | Cache, 38 | FAAS 39 | } sky_core_span_layer; 40 | 41 | typedef struct sky_core_span_t { 42 | int refs_total; 43 | int refs_size; 44 | 45 | int tags_total; 46 | int tags_size; 47 | 48 | int logs_total; 49 | int logs_size; 50 | 51 | // Tracing.proto 52 | int spanId; 53 | int parentSpanId; 54 | long startTime; 55 | long endTime; 56 | sky_core_segment_ref_t **refs; 57 | char *operationName; 58 | char *peer; 59 | sky_core_span_type spanType; 60 | sky_core_span_layer spanLayer; 61 | int componentId; 62 | bool isError; 63 | sky_core_tag_t **tags; 64 | sky_core_log_t **logs; 65 | bool skipAnalysis; 66 | } sky_core_span_t; 67 | 68 | sky_core_span_t *sky_core_span_new(sky_core_span_type type, sky_core_span_layer layer, int componentId); 69 | 70 | void sky_core_span_set_end_time(sky_core_span_t *span); 71 | 72 | void sky_core_span_add_refs(sky_core_span_t *span, sky_core_segment_ref_t *ref); 73 | 74 | void sky_core_span_set_operation_name(sky_core_span_t *span, char *name); 75 | 76 | void sky_core_span_set_peer(sky_core_span_t *span, char *peer); 77 | 78 | void sky_core_span_set_error(sky_core_span_t *span, bool isError); 79 | 80 | void sky_core_span_add_tag(sky_core_span_t *span, sky_core_tag_t *tag); 81 | 82 | int sky_core_span_to_json(char **json, sky_core_span_t *span); 83 | 84 | //class SkyCoreSpan { 85 | //public: 86 | // SkyCoreSpan(); 87 | // 88 | // ~SkyCoreSpan(); 89 | // 90 | // int getSpanId() const; 91 | // 92 | // int getParentSpanId() const; 93 | // 94 | // long getStartTime() const; 95 | // 96 | // long getEndTime() const; 97 | // 98 | // const std::vector &getRefs(); 99 | // 100 | // const std::string &getOperationName(); 101 | // 102 | // const std::string &getPeer(); 103 | // 104 | // SkyCoreSpanType getSpanType(); 105 | // 106 | // SkyCoreSpanLayer getSpanLayer(); 107 | // 108 | // int getComponentId() const; 109 | // 110 | // bool getIsError() const; 111 | // 112 | // const std::vector &getTags(); 113 | // 114 | // const std::vector &getLogs(); 115 | // 116 | // bool getSkipAnalysis() const; 117 | // 118 | // // SET 119 | // void setSpanId(int id); 120 | // 121 | // void setParentSpanId(int id); 122 | // 123 | // void setEndTIme(); 124 | // 125 | // void pushRefs(SkyCoreSegmentReference *ref); 126 | // 127 | // void setOperationName(const std::string &name); 128 | // 129 | // void setPeer(const std::string &peer); 130 | // 131 | // void setSpanType(SkyCoreSpanType type); 132 | // 133 | // void setSpanLayer(SkyCoreSpanLayer layer); 134 | // 135 | // void setComponentId(int id); 136 | // 137 | // void setIsError(bool error); 138 | // 139 | // void pushTag(SkyCoreTag *tag); 140 | // 141 | // void pushLog(SkyCoreLog *log); 142 | // 143 | // void addTag(const std::string &key, const std::string &value); 144 | // 145 | // void addLog(const std::string &key, const std::string &value); 146 | // 147 | // std::string marshal(); 148 | // 149 | //private: 150 | // // Tracing.proto 151 | // int spanId; 152 | // int parentSpanId; 153 | // long startTime; 154 | // long endTime; 155 | // std::vector refs; 156 | // std::string operationName; 157 | // std::string peer; 158 | // SkyCoreSpanType spanType; 159 | // SkyCoreSpanLayer spanLayer; 160 | // int componentId; 161 | // bool isError; 162 | // std::vector tags; 163 | // std::vector logs; 164 | // bool skipAnalysis; 165 | //}; 166 | 167 | 168 | #endif //SKYWALKING_SKY_CORE_SPAN_H 169 | -------------------------------------------------------------------------------- /src/sky_core_tag.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #include "sky_core_tag.h" 20 | #include 21 | #include 22 | #include "sky_util_php.h" 23 | #include "ext/standard/php_smart_string.h" 24 | 25 | sky_core_tag_t *sky_core_tag_new(char *key, char *value) { 26 | sky_core_tag_t *tag = (sky_core_tag_t *) emalloc(sizeof(sky_core_tag_t)); 27 | tag->key = (char *) emalloc(strlen(key) + 1); 28 | memcpy(tag->key, key, strlen(key) + 1); 29 | tag->value = (char *) emalloc(strlen(value) + 1); 30 | memcpy(tag->value, value, strlen(value) + 1); 31 | return tag; 32 | } 33 | 34 | int sky_core_tag_to_json(char **json, sky_core_tag_t *tag) { 35 | smart_string str = {0}; 36 | smart_string_appendc(&str, '{'); 37 | sky_util_json_str_ex(&str, "key", tag->key, strlen(tag->key)); 38 | sky_util_json_str(&str, "value", tag->value, strlen(tag->value)); 39 | smart_string_appendc(&str, '}'); 40 | smart_string_0(&str); 41 | 42 | efree(tag->key); 43 | efree(tag->value); 44 | efree(tag); 45 | *json = str.c; 46 | return str.len; 47 | } -------------------------------------------------------------------------------- /src/sky_core_tag.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_SKY_CORE_TAG_H 20 | #define SKYWALKING_SKY_CORE_TAG_H 21 | 22 | typedef struct sky_core_tag_t { 23 | char *key; 24 | char *value; 25 | } sky_core_tag_t; 26 | 27 | sky_core_tag_t *sky_core_tag_new(char *key, char *value); 28 | 29 | int sky_core_tag_to_json(char **json, sky_core_tag_t *tag); 30 | 31 | #endif //SKYWALKING_SKY_CORE_TAG_H 32 | -------------------------------------------------------------------------------- /src/sky_execute.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #include 20 | #include 21 | #include 22 | #include "sky_execute.h" 23 | 24 | #include "php_skywalking.h" 25 | 26 | #include "sky_plugin_predis.h" 27 | #include "sky_plugin_grpc.h" 28 | #include "sky_plugin_redis.h" 29 | #include "sky_plugin_memcached.h" 30 | #include "sky_plugin_yar.h" 31 | #include "sky_plugin_rabbit_mq.h" 32 | #include "sky_plugin_hyperf_guzzle.h" 33 | #include "sky_plugin_swoole_curl.h" 34 | #include "sky_pdo.h" 35 | #include "sky_plugin_mysqli.h" 36 | #include "sky_module.h" 37 | #include "sky_core_segment.h" 38 | 39 | void (*ori_execute_ex)(zend_execute_data *execute_data) = nullptr; 40 | 41 | void (*ori_execute_internal)(zend_execute_data *execute_data, zval *return_value) = nullptr; 42 | 43 | void sky_execute_ex(zend_execute_data *execute_data) { 44 | 45 | zend_function *fn = execute_data->func; 46 | int is_class = fn->common.scope != nullptr && fn->common.scope->name != nullptr; 47 | char *class_name = is_class ? ZSTR_VAL(fn->common.scope->name) : nullptr; 48 | char *function_name = fn->common.function_name != nullptr ? ZSTR_VAL(fn->common.function_name) : nullptr; 49 | 50 | // swoole 51 | bool swoole = false; 52 | int64_t request_id = -1; 53 | bool afterExec = true; 54 | zval *sw_response; 55 | if (SKY_IS_SWOOLE(function_name) || SKY_IS_SWOOLE_FRAMEWORK(class_name, function_name)) { 56 | uint32_t arg_count = ZEND_CALL_NUM_ARGS(execute_data); 57 | if (arg_count == 2) { 58 | zval *sw_request = ZEND_CALL_ARG(execute_data, 1); 59 | sw_response = ZEND_CALL_ARG(execute_data, 2); 60 | if (Z_TYPE_P(sw_request) == IS_OBJECT && Z_TYPE_P(sw_response) == IS_OBJECT) { 61 | if (strcmp(ZSTR_VAL(Z_OBJ_P(sw_request)->ce->name), "Swoole\\Http\\Request") == 0) { 62 | if (strcmp(ZSTR_VAL(Z_OBJ_P(sw_response)->ce->name), "Swoole\\Http\\Response") == 0) { 63 | swoole = true; 64 | zval *z_fd = sky_read_property(sw_request, "fd", 0); 65 | SKYWALKING_G(is_swoole) = true; 66 | request_id = Z_LVAL_P(z_fd); 67 | sky_request_init(sw_request, request_id); 68 | } 69 | } 70 | } 71 | } 72 | } 73 | 74 | if (SKYWALKING_G(is_swoole)) { 75 | if (sky_get_segment(execute_data, request_id) == nullptr) { 76 | ori_execute_ex(execute_data); 77 | return; 78 | } 79 | } else { 80 | if (sky_get_segment(execute_data, 0) == nullptr) { 81 | ori_execute_ex(execute_data); 82 | return; 83 | } 84 | } 85 | 86 | SkyCoreSpan *span = nullptr; 87 | 88 | if (class_name != nullptr && function_name != nullptr) { 89 | if (strcmp(function_name, "executeCommand") == 0) { 90 | span = sky_predis(execute_data, class_name, function_name); 91 | } else if (strcmp(class_name, "Grpc\\BaseStub") == 0) { 92 | span = sky_plugin_grpc(execute_data, class_name, function_name); 93 | afterExec = span == nullptr; 94 | } else if (strcmp(class_name, "PhpAmqpLib\\Channel\\AMQPChannel") == 0) { 95 | span = sky_plugin_rabbit_mq(execute_data, class_name, function_name); 96 | } else if ((SKY_STRCMP(class_name, "Hyperf\\Guzzle\\CoroutineHandler") || 97 | SKY_STRCMP(class_name, "Hyperf\\Guzzle\\PoolHandler")) && 98 | SKY_STRCMP(function_name, "__invoke")) { 99 | afterExec = false; 100 | span = sky_plugin_hyperf_guzzle(execute_data, class_name, function_name); 101 | } 102 | } else if (function_name != nullptr) { 103 | if (SKY_STRCMP(function_name, "swoole_curl_exec")) { 104 | afterExec = false; 105 | sky_plugin_swoole_curl(execute_data, "", function_name); 106 | } 107 | } 108 | 109 | if (afterExec) { 110 | ori_execute_ex(execute_data); 111 | if (span != nullptr) { 112 | span->setEndTIme(); 113 | } 114 | } 115 | 116 | if (swoole) { 117 | sky_request_flush(sw_response, request_id); 118 | } 119 | } 120 | 121 | void sky_execute_internal(zend_execute_data *execute_data, zval *return_value) { 122 | 123 | if (SKYWALKING_G(is_swoole)) { 124 | if (sky_get_segment(execute_data, -1) == nullptr) { 125 | if (ori_execute_internal) { 126 | ori_execute_internal(execute_data, return_value); 127 | } else { 128 | execute_internal(execute_data, return_value); 129 | } 130 | return; 131 | } 132 | } else { 133 | if (sky_get_segment(execute_data, 0) == nullptr) { 134 | if (ori_execute_internal) { 135 | ori_execute_internal(execute_data, return_value); 136 | } else { 137 | execute_internal(execute_data, return_value); 138 | } 139 | return; 140 | } 141 | } 142 | 143 | zend_function *fn = execute_data->func; 144 | int is_class = fn->common.scope != nullptr && fn->common.scope->name != nullptr; 145 | char *class_name = is_class ? ZSTR_VAL(fn->common.scope->name) : nullptr; 146 | char *function_name = fn->common.function_name != nullptr ? ZSTR_VAL(fn->common.function_name) : nullptr; 147 | 148 | if (class_name != nullptr && function_name != nullptr) { 149 | if (strcmp(class_name, "Swoole\\Http\\Response") == 0 && strcmp(function_name, "status") == 0) { 150 | auto *segment = sky_get_segment(execute_data, -1);; 151 | uint32_t arg_count = ZEND_CALL_NUM_ARGS(execute_data); 152 | if (arg_count >= 1) { 153 | zval *status = ZEND_CALL_ARG(execute_data, 1); 154 | if (Z_TYPE_P(status) == IS_LONG && segment != nullptr) { 155 | segment->setStatusCode(Z_LVAL_P(status)); 156 | } 157 | } 158 | } 159 | } 160 | 161 | SkyCoreSpan *span = nullptr; 162 | if (class_name != nullptr) { 163 | if (strcmp(class_name, "PDO") == 0 || strcmp(class_name, "PDOStatement") == 0) { 164 | span = sky_pdo(execute_data, class_name, function_name); 165 | } else if (strcmp(class_name, "mysqli") == 0){ 166 | span = sky_plugin_mysqli(execute_data, class_name, function_name); 167 | } else if (strcmp(class_name, "Redis") == 0) { 168 | span = sky_plugin_redis(execute_data, class_name, function_name); 169 | } else if (strcmp(class_name, "Memcached") == 0) { 170 | span = sky_plugin_memcached(execute_data, class_name, function_name); 171 | } else if (strcmp(class_name, "Yar_Client") == 0) { 172 | span = sky_plugin_yar_client(execute_data, class_name, function_name); 173 | } else if (strcmp(class_name, "Yar_Server") == 0) { 174 | span = sky_plugin_yar_server(execute_data, class_name, function_name); 175 | } 176 | } else if (function_name != nullptr) { 177 | if (strcmp(function_name, "mysqli_") > 0) { 178 | span = sky_plugin_mysqli(execute_data, "", function_name); 179 | } 180 | } 181 | 182 | if (ori_execute_internal) { 183 | ori_execute_internal(execute_data, return_value); 184 | } else { 185 | execute_internal(execute_data, return_value); 186 | } 187 | 188 | if (span != nullptr) { 189 | // catch errors add to span log 190 | if (class_name != nullptr) { 191 | if (strcmp(class_name, "PDO") == 0 || strcmp(class_name, "PDOStatement") == 0) { 192 | if (Z_TYPE_P(return_value) == IS_FALSE) { 193 | span->setIsError(true); 194 | sky_pdo_check_errors(execute_data, span); 195 | } 196 | } else if (strcmp(class_name, "mysqli") == 0){ 197 | if (Z_TYPE_P(return_value) == IS_FALSE) { 198 | span->setIsError(true); 199 | sky_plugin_mysqli_check_errors(execute_data, span, 1); 200 | } 201 | } 202 | } else if (function_name != nullptr) { 203 | if (strcmp(function_name, "mysqli_") > 0) { 204 | if (Z_TYPE_P(return_value) == IS_FALSE) { 205 | span->setIsError(true); 206 | sky_plugin_mysqli_check_errors(execute_data, span, 0); 207 | } 208 | } 209 | 210 | } 211 | span->setEndTIme(); 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/sky_execute.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_SKY_EXECUTE_H 20 | #define SKYWALKING_SKY_EXECUTE_H 21 | 22 | #include "php_skywalking.h" 23 | 24 | void sky_execute_ex(zend_execute_data *execute_data); 25 | 26 | void sky_execute_internal(zend_execute_data *execute_data, zval *return_value); 27 | 28 | #endif //SKYWALKING_SKY_EXECUTE_H 29 | -------------------------------------------------------------------------------- /src/sky_log.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "php_skywalking.h" 23 | 24 | static std::ofstream log_fs; 25 | 26 | void sky_log(std::string log) { 27 | if (SKYWALKING_G(log_enable) && !log_fs.is_open()) { 28 | log_fs.open(SKYWALKING_G(log_path), std::ios::app); 29 | } 30 | 31 | if (log_fs.is_open()) { 32 | log_fs << log << std::endl; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/sky_log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | #include 18 | 19 | #ifndef SKYWALKING_SKY_LOG_H 20 | #define SKYWALKING_SKY_LOG_H 21 | 22 | void sky_log(std::string log); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/sky_module.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #include 20 | #include 21 | #include "sky_module.h" 22 | #include 23 | 24 | #include "sky_core_segment.h" 25 | #include "sky_utils.h" 26 | #include "sky_plugin_curl.h" 27 | #include "sky_execute.h" 28 | #include "sky_plugin_error.h" 29 | #include "sky_log.h" 30 | #include "sky_rate_limit.h" 31 | #include "sky_go_wrapper.h" 32 | #include "sky_go_utils.h" 33 | #include "sys/ipc.h" 34 | #include "sys/shm.h" 35 | 36 | extern mutex_service *ms; 37 | 38 | extern void (*ori_execute_ex)(zend_execute_data *execute_data); 39 | 40 | extern void (*ori_execute_internal)(zend_execute_data *execute_data, zval *return_value); 41 | 42 | extern void (*orig_curl_exec)(INTERNAL_FUNCTION_PARAMETERS); 43 | 44 | extern void (*orig_curl_setopt)(INTERNAL_FUNCTION_PARAMETERS); 45 | 46 | extern void (*orig_curl_setopt_array)(INTERNAL_FUNCTION_PARAMETERS); 47 | 48 | extern void (*orig_curl_close)(INTERNAL_FUNCTION_PARAMETERS); 49 | 50 | void sky_module_init() { 51 | 52 | key_t key = ftok("./", 1); 53 | if (key < 0) { 54 | return; 55 | } 56 | const int id = shmget(key, sizeof(mutex_service), IPC_CREAT | 0666); 57 | if (id < 0) { 58 | return; 59 | } 60 | ms = (mutex_service *) shmat(id, nullptr, SHM_R | SHM_W); 61 | ms->id = id; 62 | pthread_mutexattr_init(&(ms->lock_attr)); 63 | pthread_mutexattr_setpshared(&(ms->lock_attr), PTHREAD_PROCESS_SHARED); 64 | pthread_mutex_init(&(ms->lock), &(ms->lock_attr)); 65 | 66 | 67 | 68 | ori_execute_ex = zend_execute_ex; 69 | zend_execute_ex = sky_execute_ex; 70 | 71 | ori_execute_internal = zend_execute_internal; 72 | zend_execute_internal = sky_execute_internal; 73 | 74 | if (SKYWALKING_G(error_handler_enable)) { 75 | sky_plugin_error_init(); 76 | } 77 | 78 | // bind curl 79 | zend_function *old_function; 80 | if ((old_function = SKY_OLD_FN("curl_exec")) != nullptr) { 81 | orig_curl_exec = old_function->internal_function.handler; 82 | old_function->internal_function.handler = sky_curl_exec_handler; 83 | } 84 | if ((old_function = SKY_OLD_FN("curl_setopt")) != nullptr) { 85 | orig_curl_setopt = old_function->internal_function.handler; 86 | old_function->internal_function.handler = sky_curl_setopt_handler; 87 | } 88 | if ((old_function = SKY_OLD_FN("curl_setopt_array")) != nullptr) { 89 | orig_curl_setopt_array = old_function->internal_function.handler; 90 | old_function->internal_function.handler = sky_curl_setopt_array_handler; 91 | } 92 | if ((old_function = SKY_OLD_FN("curl_close")) != nullptr) { 93 | orig_curl_close = old_function->internal_function.handler; 94 | old_function->internal_function.handler = sky_curl_close_handler; 95 | } 96 | 97 | auto *segments = new std::unordered_map; 98 | SKYWALKING_G(segment) = segments; 99 | 100 | auto *rate_limiter = new FixedWindowRateLimiter(SKYWALKING_G(sample_n_per_3_secs)); 101 | SKYWALKING_G(rate_limiter) = rate_limiter; 102 | 103 | GoString address = NewGoString(SKYWALKING_G(grpc), sizeof(SKYWALKING_G(grpc)) - 1); 104 | GoString server = NewGoString(SKYWALKING_G(app_code), sizeof(SKYWALKING_G(app_code)) - 1); 105 | GoString instance = NewGoString(SKYWALKING_G(instance_name), sizeof(SKYWALKING_G(instance_name)) - 1); 106 | GoString realInstance = NewProtocol(address, server, instance); 107 | pthread_mutex_lock(&(ms->lock)); 108 | strcpy(ms->service, server.p); 109 | strcpy(ms->serviceInstance, std::string(realInstance.p, realInstance.n).c_str()); 110 | pthread_mutex_unlock(&(ms->lock)); 111 | ReportInstanceProperties(); 112 | } 113 | 114 | void sky_module_cleanup() { 115 | 116 | if (ms != nullptr) { 117 | pthread_mutex_destroy(&(ms->lock)); 118 | pthread_mutexattr_destroy(&(ms->lock_attr)); 119 | shmctl(ms->id, IPC_RMID, nullptr); 120 | } 121 | 122 | auto *segments = static_cast *>(SKYWALKING_G(segment)); 123 | for (auto entry : *segments) { 124 | delete entry.second; 125 | } 126 | 127 | delete segments; 128 | delete static_cast(SKYWALKING_G(rate_limiter)); 129 | } 130 | 131 | void sky_request_init(zval *request, uint64_t request_id) { 132 | array_init(&SKYWALKING_G(curl_header)); 133 | 134 | if (!static_cast(SKYWALKING_G(rate_limiter))->validate()) { 135 | auto *segment = new SkyCoreSegment(""); 136 | segment->setSkip(true); 137 | (void)sky_insert_segment(request_id, segment); 138 | 139 | return; 140 | } 141 | 142 | zval *carrier = nullptr; 143 | zval *sw, *peer_val; 144 | std::string header; 145 | std::string uri; 146 | std::string peer; 147 | 148 | if (request != nullptr) { 149 | zval *swoole_header = sky_read_property(request, "header", 0); 150 | zval *swoole_server = sky_read_property(request, "server", 0); 151 | 152 | if (SKYWALKING_G(version) == 8) { 153 | sw = zend_hash_str_find(Z_ARRVAL_P(swoole_header), "sw8", sizeof("sw8") - 1); 154 | } else { 155 | sw = nullptr; 156 | } 157 | 158 | header = (sw != nullptr ? Z_STRVAL_P(sw) : ""); 159 | 160 | uri = Z_STRVAL_P(zend_hash_str_find(Z_ARRVAL_P(swoole_server), "request_uri", sizeof("request_uri") - 1)); 161 | 162 | peer_val = zend_hash_str_find(Z_ARRVAL_P(swoole_header), "host", sizeof("host") - 1); 163 | if (peer_val != nullptr) { 164 | peer = Z_STRVAL_P(peer_val); 165 | } else { 166 | char hostname[HOST_NAME_MAX + 1]; 167 | if (gethostname(hostname, sizeof(hostname))) { 168 | hostname[0] = '\0'; 169 | } 170 | peer_val = zend_hash_str_find(Z_ARRVAL_P(swoole_server), "server_port", sizeof("server_port") - 1); 171 | peer += hostname; 172 | peer += ":"; 173 | peer += std::to_string(Z_LVAL_P(peer_val)); 174 | } 175 | } else { 176 | 177 | } 178 | 179 | } 180 | -------------------------------------------------------------------------------- /src/sky_module.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_SKY_MODULE_H 20 | #define SKYWALKING_SKY_MODULE_H 21 | 22 | #include "php_skywalking.h" 23 | 24 | #define SKY_OLD_FN(n) static_cast(zend_hash_str_find_ptr(CG(function_table), n, sizeof(n) - 1)) 25 | 26 | void sky_module_init(); 27 | 28 | void sky_module_cleanup(); 29 | 30 | void sky_request_init(zval *request, uint64_t request_id); 31 | 32 | 33 | #endif //SKYWALKING_SKY_MODULE_H 34 | -------------------------------------------------------------------------------- /src/sky_pdo.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #include 20 | #include "sky_pdo.h" 21 | #include "sky_utils.h" 22 | 23 | #include "sky_core_segment.h" 24 | 25 | #include "php_skywalking.h" 26 | 27 | SkyCoreSpan *sky_pdo(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name) { 28 | 29 | if (class_name == "PDO") { 30 | if (function_name == "exec" || function_name == "query" || 31 | function_name == "prepare" || function_name == "commit" || 32 | function_name == "begintransaction" || function_name == "rollback") { 33 | auto *segment = sky_get_segment(execute_data, -1); 34 | if (segment->skip()) { 35 | return nullptr; 36 | } 37 | 38 | auto *span = segment->createSpan(SkyCoreSpanType::Exit, SkyCoreSpanLayer::Database, 8003); 39 | span->setOperationName(class_name + "->" + function_name); 40 | 41 | uint32_t arg_count = ZEND_CALL_NUM_ARGS(execute_data); 42 | if (arg_count) { 43 | // todo statement 44 | zval *statement = ZEND_CALL_ARG(execute_data, 1); 45 | if (Z_TYPE_P(statement) == IS_STRING) { 46 | span->addTag("db.statement", Z_STRVAL_P(statement)); 47 | } 48 | } 49 | 50 | span->setPeer(sky_pdo_peer(span, execute_data)); 51 | 52 | return span; 53 | } 54 | } else { 55 | if (function_name == "execute") { 56 | auto *segment = sky_get_segment(execute_data, -1); 57 | if (segment->skip()) { 58 | return nullptr; 59 | } 60 | 61 | auto *span = segment->createSpan(SkyCoreSpanType::Exit, SkyCoreSpanLayer::Database, 8003); 62 | span->setOperationName(class_name + "->" + function_name); 63 | 64 | span->setPeer(sky_pdo_statement_peer(span, execute_data)); 65 | 66 | return span; 67 | } 68 | } 69 | 70 | 71 | return nullptr; 72 | } 73 | 74 | std::string sky_pdo_statement_peer(SkyCoreSpan *span, zend_execute_data *execute_data) { 75 | pdo_stmt_t *stmt = (pdo_stmt_t *) Z_PDO_STMT_P(&(execute_data->This)); 76 | 77 | if (stmt != nullptr) { 78 | #if PHP_VERSION_ID >= 80100 79 | span->addTag("db.statement", ZSTR_VAL(stmt->query_string)); 80 | #else 81 | span->addTag("db.statement", stmt->query_string); 82 | #endif 83 | 84 | if (stmt->dbh != nullptr) { 85 | return sky_pdo_dbh_peer(span, stmt->dbh); 86 | } 87 | } 88 | 89 | return nullptr; 90 | } 91 | 92 | std::string sky_pdo_peer(SkyCoreSpan *span, zend_execute_data *execute_data) { 93 | pdo_dbh_t *dbh = Z_PDO_DBH_P(&(execute_data)->This); 94 | 95 | if (dbh != nullptr) { 96 | return sky_pdo_dbh_peer(span, dbh); 97 | } 98 | 99 | return nullptr; 100 | } 101 | 102 | std::string sky_pdo_dbh_peer(SkyCoreSpan *span, pdo_dbh_t *dbh) { 103 | if (dbh->driver != nullptr) { 104 | span->addTag("db.type", dbh->driver->driver_name); 105 | } 106 | 107 | if (dbh->data_source != nullptr) { 108 | span->addTag("db.data_source", dbh->data_source); 109 | std::regex ws_re(";"); 110 | std::regex kv_re("="); 111 | std::string source(dbh->data_source); 112 | std::vector items(std::sregex_token_iterator(source.begin(), source.end(), ws_re, -1), std::sregex_token_iterator()); 113 | 114 | std::string host("not_found"); 115 | std::string port("3306"); 116 | 117 | for (auto item:items) { 118 | std::vector kv(std::sregex_token_iterator(item.begin(), item.end(), kv_re, -1), std::sregex_token_iterator()); 119 | if (kv.size() >= 2) { 120 | if (kv[0] == "host") { 121 | host = kv[1]; 122 | } 123 | if (kv[0] == "port") { 124 | port = kv[1]; 125 | } 126 | } 127 | } 128 | 129 | return host + ":" + port; 130 | } 131 | return nullptr; 132 | } 133 | 134 | void sky_pdo_check_errors(zend_execute_data *execute_data, SkyCoreSpan *span) { 135 | zval *obj = &(execute_data)->This, property, return_ptr; 136 | ZVAL_STRING(&property, "errorInfo"); 137 | 138 | call_user_function(CG(function_table), obj, &property, &return_ptr, 0, nullptr); 139 | if (Z_TYPE(return_ptr) == IS_ARRAY) { 140 | span->pushLog(new SkyCoreLog("SQLSTATE", Z_STRVAL_P(zend_hash_index_find(Z_ARRVAL(return_ptr), 0)))); 141 | span->pushLog(new SkyCoreLog("Error Code", std::to_string(Z_LVAL_P(zend_hash_index_find(Z_ARRVAL(return_ptr), 1))))); 142 | span->pushLog(new SkyCoreLog("Error", Z_STRVAL_P(zend_hash_index_find(Z_ARRVAL(return_ptr), 2)))); 143 | } 144 | 145 | zval_dtor(&return_ptr); 146 | zval_dtor(&property); 147 | } 148 | -------------------------------------------------------------------------------- /src/sky_pdo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_SKY_PDO_H 20 | #define SKYWALKING_SKY_PDO_H 21 | 22 | #include "php_skywalking.h" 23 | #include "sky_core_span.h" 24 | #include 25 | 26 | SkyCoreSpan *sky_pdo(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name); 27 | 28 | std::string sky_pdo_statement_peer(SkyCoreSpan *span, zend_execute_data *execute_data); 29 | 30 | std::string sky_pdo_peer(SkyCoreSpan *span, zend_execute_data *execute_data); 31 | 32 | std::string sky_pdo_dbh_peer(SkyCoreSpan *span, pdo_dbh_t *dbh); 33 | 34 | void sky_pdo_check_errors(zend_execute_data *execute_data, SkyCoreSpan *span); 35 | 36 | #endif //SKYWALKING_SKY_PDO_H 37 | -------------------------------------------------------------------------------- /src/sky_plugin_curl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_SKY_PLUGIN_CURL_H 20 | #define SKYWALKING_SKY_PLUGIN_CURL_H 21 | 22 | #include "php.h" 23 | #include 24 | 25 | #if PHP_VERSION_ID >= 80000 26 | #include "ext/curl/php_curl.h" 27 | #endif 28 | 29 | #define SKY_CURLOPT_HTTPHEADER 9923 30 | 31 | void sky_plugin_curl_hooks(); 32 | 33 | ZEND_NAMED_FUNCTION(sky_curl_setopt_handler); 34 | 35 | ZEND_NAMED_FUNCTION(sky_curl_setopt_array_handler); 36 | 37 | ZEND_NAMED_FUNCTION(sky_curl_exec_handler); 38 | 39 | ZEND_NAMED_FUNCTION(sky_curl_close_handler); 40 | 41 | #endif //SKYWALKING_SKY_PLUGIN_CURL_H 42 | -------------------------------------------------------------------------------- /src/sky_plugin_error.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #include "sky_plugin_error.h" 20 | #include "php_skywalking.h" 21 | #include "sky_core_segment.h" 22 | #include "sky_utils.h" 23 | #include 24 | 25 | #if PHP_VERSION_ID < 80000 26 | extern void (*orig_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args); 27 | 28 | void (*orig_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) = nullptr; 29 | 30 | void sky_plugin_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) { 31 | #elif PHP_VERSION_ID >= 80000 && PHP_VERSION_ID < 80100 32 | extern void (*orig_error_cb)(int type, const char *error_filename, const uint32_t error_lineno, zend_string *message); 33 | 34 | void (*orig_error_cb)(int type, const char *error_filename, const uint32_t error_lineno, zend_string *message) = nullptr; 35 | 36 | void sky_plugin_error_cb(int type, const char *error_filename, const uint32_t error_lineno, zend_string *message) { 37 | #else 38 | extern void (*zend_error_cb)(int type, zend_string *error_filename, const uint32_t error_lineno, zend_string *message); 39 | 40 | void (*orig_error_cb)(int type, zend_string *error_filename, const uint32_t error_lineno, zend_string *message) = nullptr; 41 | 42 | void sky_plugin_error_cb(int type, zend_string *error_filename, const uint32_t error_lineno, zend_string *message) { 43 | #endif 44 | std::string level; 45 | bool isError = EG(error_reporting) & type; 46 | switch (type) { 47 | case E_ERROR: 48 | case E_PARSE: 49 | case E_CORE_ERROR: 50 | case E_COMPILE_ERROR: 51 | case E_USER_ERROR: 52 | case E_RECOVERABLE_ERROR: 53 | level = "ERROR"; 54 | break; 55 | case E_WARNING: 56 | case E_CORE_WARNING: 57 | case E_COMPILE_WARNING: 58 | case E_USER_WARNING: 59 | level = "WARNING"; 60 | break; 61 | case E_NOTICE: 62 | case E_USER_NOTICE: 63 | case E_STRICT: 64 | case E_DEPRECATED: 65 | case E_USER_DEPRECATED: 66 | level = "NOTICE"; 67 | break; 68 | default: 69 | level = "E_" + std::to_string(type); 70 | break; 71 | } 72 | #if PHP_VERSION_ID >= 80100 73 | std::string log = ZSTR_VAL(error_filename); 74 | #else 75 | std::string log = error_filename; 76 | #endif 77 | #if PHP_VERSION_ID < 80000 78 | char *msg; 79 | va_list args_copy; 80 | va_copy(args_copy, args); 81 | vspprintf(&msg, 0, format, args_copy); 82 | va_end(args_copy); 83 | log += "(" + std::to_string(error_lineno) + "): " + msg; 84 | efree(msg); 85 | #else 86 | log += "(" + std::to_string(error_lineno) + "): " + message->val; 87 | #endif 88 | 89 | if (!SKYWALKING_G(is_swoole) && SKYWALKING_G(enable) && SKYWALKING_G(segment) != nullptr) { 90 | auto segment = sky_get_segment(0); 91 | if (segment != nullptr && !segment->skip()) { 92 | auto span = segment->firstSpan(); 93 | span->addLog(level, log); 94 | if (isError) { 95 | span->setIsError(true); 96 | } 97 | } 98 | } 99 | 100 | #if PHP_VERSION_ID < 80000 101 | orig_error_cb(type, error_filename, error_lineno, format, args); 102 | #elif PHP_VERSION_ID >= 80000 && PHP_VERSION_ID < 80100 103 | orig_error_cb(type, error_filename, error_lineno, message); 104 | #else 105 | orig_error_cb(type, error_filename, error_lineno, message); 106 | #endif 107 | } 108 | 109 | void sky_plugin_error_init() { 110 | orig_error_cb = zend_error_cb; 111 | zend_error_cb = sky_plugin_error_cb; 112 | } 113 | -------------------------------------------------------------------------------- /src/sky_plugin_error.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_SKY_PLUGIN_ERROR_H 20 | #define SKYWALKING_SKY_PLUGIN_ERROR_H 21 | 22 | void sky_plugin_error_init(); 23 | 24 | #endif //SKYWALKING_SKY_PLUGIN_ERROR_H 25 | -------------------------------------------------------------------------------- /src/sky_plugin_grpc.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | 20 | #include "sky_plugin_grpc.h" 21 | #include "sky_core_segment.h" 22 | 23 | #include "php_skywalking.h" 24 | #include "sky_utils.h" 25 | 26 | extern void (*ori_execute_ex)(zend_execute_data *execute_data); 27 | 28 | SkyCoreSpan *sky_plugin_grpc(zend_execute_data *execute_data, char *class_name, char *function_name) { 29 | std::string _class_name(class_name); 30 | std::string _function_name(function_name); 31 | 32 | if (_function_name == "_simpleRequest" || _function_name == "_clientStreamRequest" || 33 | _function_name == "_serverStreamRequest" || _function_name == "_bidiRequest") { 34 | 35 | auto *segment = sky_get_segment(execute_data, -1); 36 | if (segment->skip()) { 37 | return nullptr; 38 | } 39 | 40 | auto *span = segment->createSpan(SkyCoreSpanType::Exit, SkyCoreSpanLayer::RPCFramework, 23); 41 | span->setOperationName(_class_name + "->" + _function_name); 42 | span->addTag("rpc.type", "grpc"); 43 | 44 | zval *method = ZEND_CALL_ARG(execute_data, 1); 45 | if (Z_TYPE_P(method) == IS_STRING) { 46 | span->addTag("rpc.method", Z_STRVAL_P(method)); 47 | } 48 | 49 | zval *hostname = sky_read_property(&(execute_data->This), "hostname", 1); 50 | zval *hostname_override = sky_read_property(&(execute_data->This), "hostname_override", 1); 51 | 52 | if (hostname_override != nullptr && Z_TYPE_P(hostname_override) == IS_STRING) { 53 | span->setPeer(Z_STRVAL_P(hostname_override)); 54 | } else if (hostname != nullptr && Z_TYPE_P(hostname) == IS_STRING) { 55 | span->setPeer(Z_STRVAL_P(hostname)); 56 | } 57 | 58 | zval *metadata; 59 | int offset = 4; 60 | if (_function_name == "_simpleRequest" || _function_name == "_serverStreamRequest") { 61 | metadata = ZEND_CALL_ARG(execute_data, 4); 62 | offset = 4; 63 | } else if (_function_name == "_clientStreamRequest" || _function_name == "_bidiRequest") { 64 | metadata = ZEND_CALL_ARG(execute_data, 3); 65 | offset = 3; 66 | } 67 | 68 | std::string sw_header = segment->createHeader(span); 69 | zval *sw8_val; 70 | #if PHP_MAJOR_VERSION < 7 71 | MAKE_STD_ZVAL(sw8_val); 72 | array_init(sw8_val); 73 | add_next_index_stringl(sw8_val, sw_header.c_str(), sw_header.length(), 1); 74 | #else 75 | sw8_val = (zval *)emalloc(sizeof(zval)); 76 | array_init(sw8_val); 77 | add_next_index_stringl(sw8_val, sw_header.c_str(), sw_header.length()); 78 | #endif 79 | if (nullptr != metadata) { 80 | if (Z_TYPE_P(metadata) == IS_UNDEF) { 81 | array_init(metadata); 82 | add_assoc_zval(metadata, "sw8", sw8_val); 83 | ZVAL_ARR(ZEND_CALL_ARG(execute_data, offset), Z_ARR_P(metadata)); 84 | execute_data->This.u2.num_args = offset; 85 | } else if (Z_TYPE_P(metadata) == IS_ARRAY) { 86 | SEPARATE_ARRAY(metadata); 87 | add_assoc_zval(metadata, "sw8", sw8_val); 88 | } 89 | } 90 | 91 | ori_execute_ex(execute_data); 92 | #if PHP_MAJOR_VERSION >= 7 93 | efree(sw8_val); 94 | #endif 95 | span->setEndTIme(); 96 | return span; 97 | } 98 | 99 | 100 | return nullptr; 101 | } 102 | -------------------------------------------------------------------------------- /src/sky_plugin_grpc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_SKY_PLUGIN_GRPC_H 20 | #define SKYWALKING_SKY_PLUGIN_GRPC_H 21 | 22 | #include "php_skywalking.h" 23 | 24 | #include "sky_core_span.h" 25 | 26 | SkyCoreSpan *sky_plugin_grpc(zend_execute_data *execute_data, char *class_name, char *function_name); 27 | 28 | #endif //SKYWALKING_SKY_PLUGIN_GRPC_H 29 | -------------------------------------------------------------------------------- /src/sky_plugin_hyperf_guzzle.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #include "sky_plugin_hyperf_guzzle.h" 20 | #include "php_skywalking.h" 21 | #include "sky_core_segment.h" 22 | #include "sky_utils.h" 23 | 24 | extern void (*ori_execute_ex)(zend_execute_data *execute_data); 25 | 26 | SkyCoreSpan *sky_plugin_hyperf_guzzle(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name) { 27 | 28 | auto *segment = sky_get_segment(execute_data, -1); 29 | if (segment->skip()) { 30 | return nullptr; 31 | } 32 | 33 | auto *span = segment->createSpan(SkyCoreSpanType::Exit, SkyCoreSpanLayer::Http, 8002); 34 | 35 | uint32_t arg_count = ZEND_CALL_NUM_ARGS(execute_data); 36 | 37 | if (arg_count >= 1) { 38 | zval *request = ZEND_CALL_ARG(execute_data, 1); 39 | zval uri; 40 | #if PHP_VERSION_ID < 80000 41 | zend_call_method(request, Z_OBJCE_P(request), nullptr, ZEND_STRL("geturi"), &uri, 0, nullptr, nullptr); 42 | #else 43 | zend_call_method(Z_OBJ_P(request), Z_OBJCE_P(request), nullptr, ZEND_STRL("geturi"), &uri, 0, nullptr, nullptr); 44 | #endif 45 | 46 | if (!Z_ISUNDEF(uri)) { 47 | zval scheme, host, port, path, query, to_string; 48 | int _port = 80; 49 | #if PHP_VERSION_ID < 80000 50 | zend_call_method(&uri, Z_OBJCE_P(&uri), nullptr, ZEND_STRL("getscheme"), &scheme, 0, nullptr, nullptr); 51 | zend_call_method(&uri, Z_OBJCE_P(&uri), nullptr, ZEND_STRL("gethost"), &host, 0, nullptr, nullptr); 52 | zend_call_method(&uri, Z_OBJCE_P(&uri), nullptr, ZEND_STRL("getport"), &port, 0, nullptr, nullptr); 53 | zend_call_method(&uri, Z_OBJCE_P(&uri), nullptr, ZEND_STRL("getpath"), &path, 0, nullptr, nullptr); 54 | zend_call_method(&uri, Z_OBJCE_P(&uri), nullptr, ZEND_STRL("getquery"), &query, 0, nullptr, nullptr); 55 | zend_call_method(&uri, Z_OBJCE_P(&uri), nullptr, ZEND_STRL("__tostring"), &to_string, 0, nullptr, nullptr); 56 | #else 57 | zend_call_method(Z_OBJ(uri), Z_OBJCE(uri), nullptr, ZEND_STRL("getscheme"), &scheme, 0, nullptr, nullptr); 58 | zend_call_method(Z_OBJ(uri), Z_OBJCE(uri), nullptr, ZEND_STRL("gethost"), &host, 0, nullptr, nullptr); 59 | zend_call_method(Z_OBJ(uri), Z_OBJCE(uri), nullptr, ZEND_STRL("getport"), &port, 0, nullptr, nullptr); 60 | zend_call_method(Z_OBJ(uri), Z_OBJCE(uri), nullptr, ZEND_STRL("getpath"), &path, 0, nullptr, nullptr); 61 | zend_call_method(Z_OBJ(uri), Z_OBJCE(uri), nullptr, ZEND_STRL("getquery"), &query, 0, nullptr, nullptr); 62 | zend_call_method(Z_OBJ(uri), Z_OBJCE(uri), nullptr, ZEND_STRL("__tostring"), &to_string, 0, nullptr, nullptr); 63 | #endif 64 | if (!Z_ISUNDEF(scheme) && Z_TYPE(scheme) == IS_STRING) { 65 | 66 | if (strcmp(Z_STRVAL(scheme), "http") == 0 || strcmp(Z_STRVAL(scheme), "https") == 0) { 67 | if (Z_TYPE(port) == IS_NULL && strcmp(Z_STRVAL(scheme), "https") == 0) { 68 | _port = 443; 69 | } else if (Z_TYPE(port) == IS_LONG) { 70 | _port = Z_LVAL(port); 71 | } 72 | 73 | span->setPeer(std::string(Z_STRVAL(host)) + ":" + std::to_string(_port)); 74 | span->setOperationName(Z_TYPE(path) == IS_NULL ? "/" : std::string(Z_STRVAL(path))); 75 | span->addTag("url", std::string(Z_STRVAL(to_string))); 76 | 77 | // with header 78 | std::string header = segment->createHeader(span); 79 | zval name, value; 80 | ZVAL_STRING(&name, "sw8"); 81 | array_init(&value); 82 | add_index_string(&value, 0, header.c_str()); 83 | 84 | zend_object *object = request->value.obj; 85 | std::string request_name(ZSTR_VAL(object->ce->name)); 86 | zval *headers = nullptr, *headerNames; 87 | if (request_name == "GuzzleHttp\\Psr7\\ServerRequest") { 88 | headers = sky_read_property(request, "headers", 1); 89 | headerNames = sky_read_property(request, "headerNames", 1); 90 | } else if (request_name == "GuzzleHttp\\Psr7\\Request") { 91 | headers = sky_read_property(request, "headers", 0); 92 | headerNames = sky_read_property(request, "headerNames", 0); 93 | } 94 | 95 | if (headers != nullptr && headerNames != nullptr) { 96 | add_assoc_zval_ex(headers, ZEND_STRL("sw8"), &value); 97 | add_assoc_zval_ex(headerNames, ZEND_STRL("sw8"), &name); 98 | } else { 99 | zval_ptr_dtor(&name); 100 | zval_ptr_dtor(&value); 101 | } 102 | 103 | ori_execute_ex(execute_data); 104 | span->setEndTIme(); 105 | return span; 106 | } 107 | } 108 | } 109 | } 110 | 111 | return nullptr; 112 | } 113 | -------------------------------------------------------------------------------- /src/sky_plugin_hyperf_guzzle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_SKY_PLUGIN_HYPERF_GUZZLE_H 20 | #define SKYWALKING_SKY_PLUGIN_HYPERF_GUZZLE_H 21 | 22 | #include "php_skywalking.h" 23 | #include "sky_core_span.h" 24 | 25 | SkyCoreSpan *sky_plugin_hyperf_guzzle(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name); 26 | 27 | #endif //SKYWALKING_SKY_PLUGIN_HYPERF_GUZZLE_H 28 | -------------------------------------------------------------------------------- /src/sky_plugin_memcached.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | #include "sky_plugin_memcached.h" 18 | #include "php_skywalking.h" 19 | 20 | #include "sky_core_segment.h" 21 | #include "sky_utils.h" 22 | 23 | std::vector mecKeysCommands = { 24 | "set", 25 | "setbykey", 26 | "setmulti", 27 | "setmultibykey", 28 | "add", 29 | "addbykey", 30 | "replace", 31 | "replacebykey", 32 | "append", 33 | "appendbykey", 34 | "prepend", 35 | "prependbykey", 36 | "get", 37 | "getbykey", 38 | "getmulti", 39 | "getmultibykey", 40 | "getallkeys", 41 | "delete", 42 | "deletebykey", 43 | "deletemulti", 44 | "deletemultibykey", 45 | "increment", 46 | "incrementbykey", 47 | "decrement", 48 | "decrementbykey", 49 | "getstats", 50 | "ispersistent", 51 | "ispristine", 52 | "flush", 53 | "flushbuffers", 54 | "getdelayed", 55 | "getdelayedbykey", 56 | "fetch", 57 | "fetchall", 58 | "addserver", 59 | "addservers", 60 | "getoption", 61 | "setoption", 62 | "setoptions", 63 | "getresultcode", 64 | "getserverlist", 65 | "resetserverlist", 66 | "getversion", 67 | "quit", 68 | "setsaslauthdata", 69 | "touch", 70 | "touchbykey" 71 | }; 72 | std::vector mecStrKeysCommands = { 73 | "set", 74 | "setbykey", 75 | "setmulti", 76 | "setmultibykey", 77 | "add", 78 | "addbykey", 79 | "replace", 80 | "replacebykey", 81 | "append", 82 | "appendbykey", 83 | "prepend", 84 | "prependbykey", 85 | "get", 86 | "getbykey", 87 | "getmulti", 88 | "getmultibykey", 89 | "getallkeys", 90 | "delete", 91 | "deletebykey", 92 | "deletemulti", 93 | "deletemultibykey", 94 | "increment", 95 | "incrementbykey", 96 | "decrement", 97 | "decrementbykey" 98 | }; 99 | 100 | SkyCoreSpan *sky_plugin_memcached(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name) { 101 | std::string cmd = function_name; 102 | std::transform(function_name.begin(), function_name.end(), cmd.begin(), ::tolower); 103 | if (std::find(mecKeysCommands.begin(), mecKeysCommands.end(), cmd) != mecKeysCommands.end()) { 104 | auto *segment = sky_get_segment(execute_data, -1); 105 | if (segment) { 106 | auto *span = segment->createSpan(SkyCoreSpanType::Exit, SkyCoreSpanLayer::Cache, 36); 107 | span->setOperationName(class_name + "->" + function_name); 108 | span->addTag("db.type", "memcached"); 109 | 110 | // peer 111 | if (std::find(mecStrKeysCommands.begin(), mecStrKeysCommands.end(), cmd) != mecStrKeysCommands.end()) { 112 | auto peer = sky_plugin_memcached_peer(execute_data); 113 | if (!peer.empty()) { 114 | span->setPeer(peer); 115 | } 116 | } 117 | 118 | span->addTag("memcached.command", sky_plugin_memcached_key_cmd(execute_data, cmd)); 119 | return span; 120 | } 121 | } 122 | return nullptr; 123 | } 124 | 125 | std::string sky_plugin_memcached_peer(zend_execute_data *execute_data) { 126 | std::string peer; 127 | zval *key = ZEND_CALL_ARG(execute_data, 1); 128 | zval *self = &(execute_data->This); 129 | #if PHP_VERSION_ID < 80000 130 | zval *obj = self; 131 | #else 132 | zend_object *obj = Z_OBJ_P(self); 133 | #endif 134 | zval server; 135 | zval params[1]; 136 | ZVAL_STRING(¶ms[0], Z_STRVAL_P(key)); 137 | zend_call_method(obj, Z_OBJCE_P(self), nullptr, ZEND_STRL("getserverbykey"), &server, 1, params, nullptr); 138 | 139 | if (Z_TYPE_P(&server) == IS_ARRAY) { 140 | zval *host_zval = zend_hash_str_find(Z_ARRVAL_P(&server), "host", 4); 141 | zval *port_zval = zend_hash_str_find(Z_ARRVAL_P(&server), "port", 4); 142 | peer = std::string(Z_STRVAL_P(host_zval)) + ":" + std::to_string(Z_LVAL_P(host_zval)); 143 | } 144 | 145 | zval_dtor(&server); 146 | zval_dtor(¶ms[0]); 147 | return peer; 148 | } 149 | 150 | std::string sky_plugin_memcached_key_cmd(zend_execute_data *execute_data, std::string cmd) { 151 | uint32_t arg_count = ZEND_CALL_NUM_ARGS(execute_data); 152 | std::string command = cmd; 153 | for (uint32_t i = 1; i < arg_count + 1; ++i) { 154 | command = command.append(" "); 155 | zval *p = ZEND_CALL_ARG(execute_data, i); 156 | if (Z_TYPE_P(p) == IS_ARRAY) { 157 | command = command.append(sky_json_encode(p)); 158 | continue; 159 | } 160 | 161 | zval str_p; 162 | 163 | ZVAL_COPY(&str_p, p); 164 | if (Z_TYPE_P(&str_p) != IS_ARRAY && Z_TYPE_P(&str_p) != IS_STRING) { 165 | convert_to_string(&str_p); 166 | } 167 | 168 | std::string str = Z_STRVAL_P(&str_p); 169 | 170 | command = command.append(str); 171 | str.clear(); 172 | str.shrink_to_fit(); 173 | zval_dtor(&str_p); 174 | } 175 | 176 | if (!command.empty()) { 177 | std::transform(command.begin(), command.end(), command.begin(), ::tolower); 178 | } 179 | return command; 180 | } 181 | -------------------------------------------------------------------------------- /src/sky_plugin_memcached.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef SKYWALKING_SRC_SKY_PLUGIN_MEMCACHED_H_ 19 | #define SKYWALKING_SRC_SKY_PLUGIN_MEMCACHED_H_ 20 | 21 | #include "php_skywalking.h" 22 | #include "sky_utils.h" 23 | #include 24 | #include 25 | #include 26 | #include "sky_core_span.h" 27 | #include "sky_core_segment.h" 28 | 29 | SkyCoreSpan *sky_plugin_memcached(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name); 30 | 31 | std::string sky_plugin_memcached_peer(zend_execute_data *execute_data); 32 | 33 | std::string sky_plugin_memcached_key_cmd(zend_execute_data *execute_data, std::string cmd); 34 | #endif //SKYWALKING_SRC_SKY_PLUGIN_MEMCACHED_H_ 35 | -------------------------------------------------------------------------------- /src/sky_plugin_mysqli.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #include "sky_plugin_mysqli.h" 20 | #include "sky_core_log.h" 21 | #include "sky_core_segment.h" 22 | #include "sky_utils.h" 23 | #include "php_skywalking.h" 24 | 25 | #ifdef MYSQLI_USE_MYSQLND 26 | #include "ext/mysqli/php_mysqli_structs.h" 27 | 28 | void sky_mysqli_peer(SkyCoreSpan *span, mysqli_object *mysqli) { 29 | MYSQLI_RESOURCE *my_res = (MYSQLI_RESOURCE *) mysqli->ptr; 30 | if (my_res && my_res->ptr) { 31 | MY_MYSQL *mysql = (MY_MYSQL *) my_res->ptr; 32 | if (mysql->mysql) { 33 | #if PHP_VERSION_ID >= 70100 34 | std::string host = "127.0.0.1"; 35 | if(mysql->mysql->data->hostname.l > 0){ 36 | host = mysql->mysql->data->hostname.s; 37 | } 38 | #else 39 | std::string host = mysql->mysql->data->host; 40 | #endif 41 | span->addTag("db.type", "mysql"); 42 | span->setPeer(host + ":" + std::to_string(mysql->mysql->data->port)); 43 | } 44 | } 45 | } 46 | #endif 47 | 48 | SkyCoreSpan *sky_plugin_mysqli(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name) { 49 | #ifdef MYSQLI_USE_MYSQLND 50 | mysqli_object *mysqli = nullptr; 51 | bool is_pdo_func = function_name == "query" || function_name == "autocommit" || function_name == "commit" || function_name == "rollback"; 52 | bool is_mysqli_func = function_name == "mysqli_query" || function_name == "mysqli_autocommit" || function_name == "mysqli_commit" || function_name == "mysqli_rollback"; 53 | if (is_pdo_func || is_mysqli_func) { 54 | auto *segment = sky_get_segment(execute_data, -1); 55 | if (segment->skip()) { 56 | return nullptr; 57 | } 58 | 59 | auto *span = segment->createSpan(SkyCoreSpanType::Exit, SkyCoreSpanLayer::Database, 8004); 60 | uint32_t arg_count = ZEND_CALL_NUM_ARGS(execute_data); 61 | 62 | zval *statement = nullptr; 63 | if (class_name == "mysqli") { 64 | span->setOperationName(class_name + "->" + function_name); 65 | if (arg_count) { 66 | statement = ZEND_CALL_ARG(execute_data, 1); 67 | } 68 | mysqli = (mysqli_object *) Z_MYSQLI_P(&(execute_data->This)); 69 | } else { //is procedural 70 | span->setOperationName(function_name); 71 | if (arg_count > 1) { 72 | statement = ZEND_CALL_ARG(execute_data, 2); 73 | } 74 | zval *obj = ZEND_CALL_ARG(execute_data, 1); 75 | if (Z_TYPE_P(obj) != IS_NULL){ 76 | mysqli = (mysqli_object *) Z_MYSQLI_P(obj); 77 | } 78 | } 79 | 80 | if (statement != nullptr && Z_TYPE_P(statement) == IS_STRING) { 81 | span->addTag("db.statement", Z_STRVAL_P(statement)); 82 | } 83 | if (mysqli != nullptr){ 84 | sky_mysqli_peer(span, mysqli); 85 | } 86 | 87 | return span; 88 | } 89 | #endif 90 | return nullptr; 91 | } 92 | 93 | void sky_plugin_mysqli_check_errors(zend_execute_data *execute_data, SkyCoreSpan *span, int is_oop) { 94 | #ifdef MYSQLI_USE_MYSQLND 95 | zval *obj, rv; 96 | if (is_oop == 1) { 97 | obj = &(execute_data)->This; 98 | } else { 99 | obj = ZEND_CALL_ARG(execute_data, 1); 100 | } 101 | #if PHP_VERSION_ID < 80000 102 | zend_read_property(obj->value.obj->ce, obj, ZEND_STRL("error_list"), 0, &rv); 103 | #else 104 | zend_read_property(obj->value.obj->ce, obj->value.obj, ZEND_STRL("error_list"), 0, &rv); 105 | #endif 106 | 107 | zend_string *key; 108 | zval *value, *item; 109 | ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(&rv), item) { 110 | if (Z_TYPE_P(item) == IS_ARRAY) { 111 | ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(item), key, value) { 112 | if (Z_TYPE_P(value) == IS_LONG) { 113 | span->addLog(key->val, std::to_string(Z_LVAL_P(value))); 114 | } else { 115 | span->addLog(key->val, Z_STRVAL_P(value)); 116 | } 117 | } ZEND_HASH_FOREACH_END(); 118 | } 119 | }ZEND_HASH_FOREACH_END(); 120 | 121 | zval_dtor(&rv); 122 | #endif 123 | } 124 | -------------------------------------------------------------------------------- /src/sky_plugin_mysqli.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_SKY_MYSQLI_H 20 | #define SKYWALKING_SKY_MYSQLI_H 21 | 22 | #include "php_skywalking.h" 23 | #include "sky_core_span.h" 24 | #include 25 | #ifdef MYSQLI_USE_MYSQLND 26 | #include "ext/mysqli/php_mysqli_structs.h" 27 | #endif 28 | 29 | SkyCoreSpan *sky_plugin_mysqli(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name); 30 | 31 | void sky_plugin_mysqli_check_errors(zend_execute_data *execute_data, SkyCoreSpan *span, int is_oop); 32 | 33 | #endif //SKYWALKING_SKY_MYSQLI_H 34 | -------------------------------------------------------------------------------- /src/sky_plugin_predis.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #include "sky_plugin_predis.h" 20 | 21 | #include "php_skywalking.h" 22 | 23 | #include "sky_core_segment.h" 24 | #include "sky_utils.h" 25 | 26 | SkyCoreSpan *sky_predis(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name) { 27 | if (class_name != "Predis\\Connection\\AbstractConnection") { 28 | return nullptr; 29 | } 30 | 31 | uint32_t args = ZEND_CALL_NUM_ARGS(execute_data); 32 | if (args) { 33 | auto *segment = sky_get_segment(execute_data, -1); 34 | if (segment->skip()) { 35 | return nullptr; 36 | } 37 | auto *span = segment->createSpan(SkyCoreSpanType::Exit, SkyCoreSpanLayer::Cache, 8006); 38 | 39 | zval *command = ZEND_CALL_ARG(execute_data, 1); 40 | 41 | zval *id = (zval *) emalloc(sizeof(zval)); 42 | zval *arguments = (zval *) emalloc(sizeof(zval)); 43 | #if PHP_VERSION_ID < 80000 44 | zend_call_method(command, Z_OBJCE_P(command), nullptr, ZEND_STRL("getid"), id, 0, nullptr, nullptr); 45 | zend_call_method(command, Z_OBJCE_P(command), nullptr, ZEND_STRL("getarguments"), arguments, 0, nullptr, 46 | nullptr); 47 | #else 48 | zend_call_method(Z_OBJ_P(command), Z_OBJCE_P(command), nullptr, ZEND_STRL("getid"), id, 0, nullptr, 49 | nullptr); 50 | zend_call_method(Z_OBJ_P(command), Z_OBJCE_P(command), nullptr, ZEND_STRL("getarguments"), arguments, 51 | 0, nullptr, nullptr); 52 | #endif 53 | 54 | if (id != nullptr && Z_TYPE_P(id) == IS_STRING) { 55 | span->setOperationName(class_name + "->" + std::string(Z_STRVAL_P(id))); 56 | span->addTag("db.type", "redis"); 57 | // other 58 | auto peer = sky_predis_peer(execute_data); 59 | if (!peer.empty()) { 60 | span->setPeer(peer); 61 | } 62 | 63 | // cmd 64 | auto cmd = sky_predis_command(id, arguments); 65 | if (!cmd.empty()) { 66 | span->addTag("redis.command", cmd); 67 | } 68 | } 69 | 70 | if (id) { 71 | zval_ptr_dtor(id); 72 | efree(id); 73 | } 74 | 75 | if (arguments) { 76 | zval_ptr_dtor(arguments); 77 | efree(arguments); 78 | } 79 | 80 | return span; 81 | } 82 | return nullptr; 83 | } 84 | 85 | std::string sky_predis_peer(zend_execute_data *execute_data) { 86 | 87 | zval *parameters_class = sky_read_property(&(execute_data->This), "parameters", 0); 88 | if (SKY_PREDIS_IS_PARAMETERS(parameters_class)) { 89 | zval *parameters = sky_read_property(parameters_class, "parameters", 0); 90 | zval *predis_host = zend_hash_str_find(Z_ARRVAL_P(parameters), "host", sizeof("host") - 1); 91 | zval *predis_port = zend_hash_str_find(Z_ARRVAL_P(parameters), "port", sizeof("port") - 1); 92 | zval port; 93 | ZVAL_COPY(&port, predis_port); 94 | if (Z_TYPE(port) != IS_LONG) { 95 | convert_to_long(&port); 96 | } 97 | 98 | if (Z_TYPE_P(predis_host) == IS_STRING && Z_TYPE(port) == IS_LONG) { 99 | char *host = ZSTR_VAL(Z_STR_P(predis_host)); 100 | return std::string(host) + ":" + std::to_string(Z_LVAL(port)); 101 | } 102 | } 103 | return ""; 104 | } 105 | 106 | std::string sky_predis_command(zval *id, zval *arguments) { 107 | if (arguments != nullptr && Z_TYPE_P(arguments) == IS_ARRAY) { 108 | zend_ulong key; 109 | zval *value, dup_value; 110 | std::string command; 111 | command += std::string(Z_STRVAL_P(id)) + " "; 112 | ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(arguments), key, value) 113 | { 114 | switch (Z_TYPE_P(value)) { 115 | case IS_STRING: 116 | command += std::string(Z_STRVAL_P(value)) + " "; 117 | break; 118 | case IS_ARRAY: 119 | break; 120 | default: 121 | ZVAL_COPY(&dup_value, value); 122 | convert_to_string(&dup_value); 123 | command += std::string(Z_STRVAL_P(&dup_value)) + " "; 124 | break; 125 | } 126 | } 127 | ZEND_HASH_FOREACH_END(); 128 | 129 | return command; 130 | } 131 | 132 | return ""; 133 | } 134 | -------------------------------------------------------------------------------- /src/sky_plugin_predis.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_SKY_PLUGIN_PREDIS_H 20 | #define SKYWALKING_SKY_PLUGIN_PREDIS_H 21 | 22 | #include "php_skywalking.h" 23 | 24 | #include "sky_utils.h" 25 | #include 26 | #include "sky_core_span.h" 27 | 28 | #define SKY_PREDIS_IS_PARAMETERS(p) SKY_IS_OBJECT(p) && sky_get_class_name(p) == "Predis\\Connection\\Parameters" 29 | 30 | #define SKY_PREDIS_IS_STREAM_CONNECTION(c) SKY_IS_OBJECT(c) && sky_get_class_name(c) == "Predis\\Connection\\StreamConnection" 31 | #define SKY_PREDIS_IS_ABSTRACT_CONNECTION(c) SKY_IS_OBJECT(c) && sky_get_class_name(c) == "Predis\\Connection\\AbstractConnection" 32 | 33 | 34 | SkyCoreSpan *sky_predis(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name); 35 | 36 | std::string sky_predis_peer(zend_execute_data *execute_data); 37 | 38 | std::string sky_predis_command(zval *id, zval *arguments); 39 | 40 | #endif //SKYWALKING_SKY_PLUGIN_PREDIS_H 41 | -------------------------------------------------------------------------------- /src/sky_plugin_rabbit_mq.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #include "sky_plugin_rabbit_mq.h" 20 | #include "sky_core_segment.h" 21 | #include "sky_utils.h" 22 | 23 | SkyCoreSpan *sky_plugin_rabbit_mq(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name) { 24 | 25 | if (function_name == "basic_publish") { 26 | auto *segment = sky_get_segment(execute_data, -1); 27 | if (segment->skip()) { 28 | return nullptr; 29 | } 30 | auto *span = segment->createSpan(SkyCoreSpanType::Exit, SkyCoreSpanLayer::MQ, 52); 31 | 32 | span->setOperationName(class_name + "->" + function_name); 33 | 34 | zval *exchange = ZEND_CALL_ARG(execute_data, 2); 35 | 36 | //span->addTag("mq.queue", "queueName"); 37 | if (Z_TYPE_P(exchange) == IS_STRING) { 38 | span->addTag("mq.topic", Z_STRVAL_P(exchange)); 39 | } 40 | 41 | // peer 42 | zval *connection = sky_read_property(&(execute_data->This), "connection", 1); 43 | if (Z_TYPE_P(connection) == IS_OBJECT) { 44 | zval *params = sky_read_property(connection, "construct_params", 1); 45 | if (Z_TYPE_P(params) == IS_ARRAY) { 46 | zval *host = zend_hash_index_find(Z_ARRVAL_P(params), 0); 47 | zval *port = zend_hash_index_find(Z_ARRVAL_P(params), 1); 48 | 49 | if (Z_TYPE_P(host) == IS_STRING) { 50 | std::string peer = std::string(Z_STRVAL_P(host)) + ":"; 51 | 52 | if (Z_TYPE_P(port) == IS_STRING) { 53 | peer += std::string(Z_STRVAL_P(port)); 54 | } else if (Z_TYPE_P(port) == IS_LONG) { 55 | peer += std::to_string(Z_LVAL_P(port)); 56 | } else { 57 | peer += "5672"; 58 | } 59 | 60 | span->setPeer(peer); 61 | span->addTag("mq.broker", peer); 62 | } 63 | } 64 | } 65 | return span; 66 | } else { 67 | return nullptr; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/sky_plugin_rabbit_mq.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_SKY_PLUGIN_RABBIT_MQ_H 20 | #define SKYWALKING_SKY_PLUGIN_RABBIT_MQ_H 21 | 22 | #include "php_skywalking.h" 23 | #include "sky_core_span.h" 24 | 25 | SkyCoreSpan *sky_plugin_rabbit_mq(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name); 26 | 27 | 28 | #endif //SKYWALKING_SKY_PLUGIN_RABBIT_MQ_H 29 | -------------------------------------------------------------------------------- /src/sky_plugin_swoole_curl.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #include 20 | #include "sky_plugin_swoole_curl.h" 21 | #include "sky_core_segment.h" 22 | #include "php_skywalking.h" 23 | #include "sky_utils.h" 24 | 25 | extern void (*ori_execute_ex)(zend_execute_data *execute_data); 26 | 27 | void sky_plugin_swoole_curl(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name) { 28 | uint32_t arg_count = ZEND_CALL_NUM_ARGS(execute_data); 29 | 30 | if (arg_count >= 1) { 31 | SkyCoreSpan *span = nullptr; 32 | 33 | zval *handle = ZEND_CALL_ARG(execute_data, 1); 34 | 35 | zval *urlInfo = sky_read_property(handle, "urlInfo", 0); 36 | zval *scheme = zend_hash_str_find(Z_ARRVAL_P(urlInfo), ZEND_STRL("scheme")); 37 | zval *host = zend_hash_str_find(Z_ARRVAL_P(urlInfo), ZEND_STRL("host")); 38 | zval *port = zend_hash_str_find(Z_ARRVAL_P(urlInfo), ZEND_STRL("port")); 39 | zval *path = zend_hash_str_find(Z_ARRVAL_P(urlInfo), ZEND_STRL("path")); 40 | 41 | if (!Z_ISUNDEF_P(scheme) && Z_TYPE_P(scheme) == IS_STRING) { 42 | std::string _scheme(Z_STRVAL_P(scheme)); 43 | std::string _host(Z_STRVAL_P(host)); 44 | int _port(Z_LVAL_P(port)); 45 | std::string _path; 46 | std::string _url; 47 | 48 | zval url; 49 | SKY_ZEND_CALL_METHOD(handle, nullptr, "geturl", &url, 0, nullptr, nullptr); 50 | 51 | if (!Z_ISUNDEF(url) && Z_TYPE(url) == IS_STRING) { 52 | _url = std::string(Z_STRVAL(url)); 53 | } 54 | 55 | if (path != nullptr && !Z_ISUNDEF_P(path) && Z_TYPE_P(path) == IS_STRING) { 56 | _path = std::string(Z_STRVAL_P(path)); 57 | } else { 58 | _path = "/"; 59 | } 60 | 61 | if (_scheme == "http" || _scheme == "https") { 62 | auto *segment = sky_get_segment(execute_data, -1); 63 | if (segment != nullptr) { 64 | span = segment->createSpan(SkyCoreSpanType::Exit, SkyCoreSpanLayer::Http, 8002); 65 | span->setPeer(_host + ":" + std::to_string(_port)); 66 | span->setOperationName(_path); 67 | span->addTag("url", _scheme + "://" + _host + ":" + std::to_string(_port) + _url); 68 | std::string header = segment->createHeader(span); 69 | 70 | zval opt, value; 71 | ZVAL_LONG(&opt, CURLOPT_HTTPHEADER); 72 | array_init(&value); 73 | add_index_string(&value, 0, ("sw8: " + header).c_str()); 74 | 75 | SKY_ZEND_CALL_METHOD(handle, nullptr, "setopt", nullptr, 2, &opt, &value); 76 | } 77 | } 78 | } 79 | 80 | ori_execute_ex(execute_data); 81 | 82 | if (span) { 83 | zval *info = sky_read_property(handle, "info", 0); 84 | zval *http_code = zend_hash_str_find(Z_ARRVAL_P(info), ZEND_STRL("http_code")); 85 | 86 | if (!Z_ISUNDEF_P(http_code) && Z_TYPE_P(http_code) == IS_LONG) { 87 | span->addTag("status_code", std::to_string(Z_LVAL_P(http_code))); 88 | if (Z_LVAL_P(http_code) >= 400) { 89 | span->setIsError(true); 90 | } 91 | } 92 | span->setEndTIme(); 93 | } 94 | } else { 95 | ori_execute_ex(execute_data); 96 | } 97 | } -------------------------------------------------------------------------------- /src/sky_plugin_swoole_curl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_SKY_PLUGIN_SWOOLE_CURL_H 20 | #define SKYWALKING_SKY_PLUGIN_SWOOLE_CURL_H 21 | 22 | #include "php_skywalking.h" 23 | #include "sky_core_span.h" 24 | 25 | void sky_plugin_swoole_curl(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name); 26 | 27 | #endif //SKYWALKING_SKY_PLUGIN_SWOOLE_CURL_H 28 | -------------------------------------------------------------------------------- /src/sky_plugin_yar.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include "sky_plugin_yar.h" 19 | #include "php_skywalking.h" 20 | #include "zend_types.h" 21 | 22 | #include "sky_core_segment.h" 23 | #include "sky_utils.h" 24 | 25 | std::vector clientKeysCommands = {"__call"}; 26 | std::vector serverKeysCommands = {"__construct"}; 27 | SkyCoreSpan *sky_plugin_yar_client(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name) { 28 | std::string cmd = function_name; 29 | std::transform(function_name.begin(), function_name.end(), cmd.begin(), ::tolower); 30 | if (std::find(clientKeysCommands.begin(), clientKeysCommands.end(), cmd) != clientKeysCommands.end()) { 31 | auto *segment = sky_get_segment(execute_data, -1); 32 | if (segment) { 33 | auto *span = segment->createSpan(SkyCoreSpanType::Exit, SkyCoreSpanLayer::RPCFramework, 8002); 34 | span->setOperationName(class_name + "->" + function_name); 35 | span->addTag("yar.type", "client"); 36 | 37 | zval *self = &(execute_data->This); 38 | #if PHP_VERSION_ID < 80000 39 | zval *obj = self; 40 | #else 41 | zend_object *obj = Z_OBJ_P(self); 42 | #endif 43 | 44 | zval *zval_uri = sky_read_property(self, "_uri", 0); 45 | /* 检索uri属性的值 */ 46 | if (zval_uri) { 47 | zval copy_zval_uri; 48 | ZVAL_DUP(©_zval_uri, zval_uri); 49 | span->addTag("yar.uri", ZSTR_VAL(Z_STR(copy_zval_uri))); 50 | 51 | php_url *url_parse = nullptr; 52 | url_parse = php_url_parse(ZSTR_VAL(Z_STR(copy_zval_uri))); 53 | if (url_parse != nullptr && url_parse->scheme != nullptr && url_parse->host != nullptr) { 54 | #if PHP_VERSION_ID >= 70300 55 | char *php_url_scheme = ZSTR_VAL(url_parse->scheme); 56 | char *php_url_host = ZSTR_VAL(url_parse->host); 57 | #else 58 | char *php_url_scheme = url_parse->scheme; 59 | char *php_url_host = url_parse->host; 60 | #endif 61 | 62 | int peer_port; 63 | if (url_parse->port) { 64 | peer_port = url_parse->port; 65 | } else { 66 | if (strcasecmp("http", php_url_scheme) == 0) { 67 | peer_port = 80; 68 | } else { 69 | peer_port = 443; 70 | } 71 | } 72 | span->setPeer(std::string(php_url_host) + ":" + std::to_string(peer_port)); 73 | } 74 | zval_dtor(©_zval_uri); 75 | } 76 | 77 | std::string sw_header = segment->createHeader(span); 78 | zval params[2]; 79 | ZVAL_LONG(¶ms[0], YAR_OPT_HEADER); 80 | zval *yar_headers = (zval *) emalloc(sizeof(zval)); 81 | bzero(yar_headers, sizeof(zval)); 82 | array_init(yar_headers); 83 | add_next_index_string(yar_headers, ("sw8: " + sw_header).c_str()); 84 | ZVAL_COPY(¶ms[1], yar_headers); 85 | zend_call_method(obj, Z_OBJCE_P(self), nullptr, ZEND_STRL("setopt"), nullptr, 2, ¶ms[0], ¶ms[1]); 86 | zval_dtor(¶ms[0]); 87 | zval_dtor(¶ms[1]); 88 | zval_dtor(yar_headers); 89 | efree(yar_headers); 90 | sw_header.shrink_to_fit(); 91 | 92 | uint32_t arg_count = ZEND_CALL_NUM_ARGS(execute_data); 93 | if (arg_count) { 94 | 95 | std::string command; 96 | for (uint32_t i = 1; i < arg_count + 1; ++i) { 97 | zval *p = ZEND_CALL_ARG(execute_data, i); 98 | if (Z_TYPE_P(p) == IS_ARRAY) { 99 | command = command.append(sky_json_encode(p)); 100 | continue; 101 | } 102 | 103 | if (i == 1 && Z_TYPE_P(p) == IS_STRING) { 104 | span->addTag("yar.method", Z_STRVAL_P(p)); 105 | } 106 | 107 | zval str_p; 108 | ZVAL_COPY(&str_p, p); 109 | if (Z_TYPE_P(&str_p) != IS_ARRAY && Z_TYPE_P(&str_p) != IS_STRING) { 110 | convert_to_string(&str_p); 111 | } 112 | 113 | std::string str = Z_STRVAL_P(&str_p); 114 | std::transform(str.begin(), str.end(), str.begin(), ::tolower); 115 | command = command.append(str); 116 | command.append(" "); 117 | str.clear(); 118 | str.shrink_to_fit(); 119 | zval_dtor(&str_p); 120 | } 121 | 122 | if (!command.empty()) { 123 | std::transform(command.begin(), command.end(), command.begin(), ::tolower); 124 | span->addTag("yar.call", command); 125 | } 126 | 127 | command.clear(); 128 | command.shrink_to_fit(); 129 | } 130 | return span; 131 | } 132 | } 133 | return nullptr; 134 | } 135 | 136 | SkyCoreSpan *sky_plugin_yar_server(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name) { 137 | std::string cmd = function_name; 138 | std::transform(function_name.begin(), function_name.end(), cmd.begin(), ::tolower); 139 | if (std::find(serverKeysCommands.begin(), serverKeysCommands.end(), cmd) != serverKeysCommands.end()) { 140 | auto *segment = sky_get_segment(execute_data, -1); 141 | if (segment) { 142 | auto *span = segment->createSpan(SkyCoreSpanType::Exit, SkyCoreSpanLayer::RPCFramework, 8002); 143 | span->setOperationName(class_name + "->" + function_name); 144 | span->addTag("yar.type", "server"); 145 | return span; 146 | } 147 | } 148 | return nullptr; 149 | } -------------------------------------------------------------------------------- /src/sky_plugin_yar.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef SKYWALKING_SRC_SKY_PLUGIN_YAR_H_ 19 | #define SKYWALKING_SRC_SKY_PLUGIN_YAR_H_ 20 | 21 | #include "php_skywalking.h" 22 | #include "sky_utils.h" 23 | #include 24 | #include 25 | #include 26 | #include "sky_core_span.h" 27 | #include "sky_core_segment.h" 28 | #define YAR_OPT_HEADER (1<<4) 29 | 30 | SkyCoreSpan *sky_plugin_yar_client(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name); 31 | 32 | SkyCoreSpan *sky_plugin_yar_server(zend_execute_data *execute_data, const std::string &class_name, const std::string &function_name); 33 | 34 | #endif //SKYWALKING_SRC_SKY_PLUGIN_YAR_H_ 35 | -------------------------------------------------------------------------------- /src/sky_rate_limit.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | 20 | #include 21 | #include 22 | #include "sky_rate_limit.h" 23 | #include "sky_log.h" 24 | 25 | FixedWindowRateLimiter::FixedWindowRateLimiter(int64_t rate, int seconds) : rate(rate), currentCount(0), resetLock(false) { 26 | if (seconds < 1) { 27 | timeWindow = std::chrono::seconds(1); 28 | } else { 29 | timeWindow = std::chrono::seconds(seconds); 30 | } 31 | 32 | this->startTime = TimePoint::clock::now(); 33 | } 34 | 35 | bool FixedWindowRateLimiter::validate() { 36 | if (this->rate < 1) { 37 | return true; 38 | } 39 | 40 | std::chrono::duration span = TimePoint::clock::now() - this->startTime; 41 | 42 | bool falseValue = false; 43 | if (span > this->timeWindow 44 | && resetLock.compare_exchange_weak(falseValue, true) 45 | && (TimePoint::clock::now() - this->startTime) > this->timeWindow) { 46 | 47 | int64_t timeSpan = static_cast(floor(span.count())); 48 | timeSpan = timeSpan - timeSpan % this->timeWindow.count(); 49 | 50 | this->startTime += std::chrono::seconds(timeSpan); 51 | span = TimePoint::clock::now() - this->startTime; 52 | this->currentCount.store(0); 53 | 54 | resetLock.store(false); 55 | } 56 | 57 | if (++this->currentCount > this->rate && span < this->timeWindow) { 58 | sky_log("rate limiter hit: " + std::to_string(this->currentCount) + "/" + std::to_string(this->rate)); 59 | return false; 60 | } 61 | 62 | return true; 63 | } 64 | -------------------------------------------------------------------------------- /src/sky_rate_limit.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_SKY_RATE_LIMIT_H 20 | #define SKYWALKING_SKY_RATE_LIMIT_H 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | class FixedWindowRateLimiter { 27 | public: 28 | using TimePoint = std::chrono::time_point; 29 | 30 | FixedWindowRateLimiter(int64_t rate, int seconds = 3); 31 | bool validate(); 32 | 33 | private: 34 | std::atomic currentCount; 35 | int64_t rate; 36 | std::chrono::duration timeWindow; // second 37 | TimePoint startTime; 38 | 39 | std::atomic_bool resetLock; 40 | }; 41 | 42 | #endif // SKYWALKING_SKY_RATE_LIMIT_H 43 | -------------------------------------------------------------------------------- /src/sky_util_base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include "sky_util_base64.h" 19 | #include 20 | #include 21 | 22 | char sky_base64_map[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 23 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 24 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 25 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}; 26 | 27 | char *sky_util_base64_decode(char *cipher) { 28 | char counts = 0; 29 | char buffer[4]; 30 | char *plain = (char *) malloc(strlen(cipher) * 3 / 4); 31 | int i = 0, p = 0; 32 | 33 | for (i = 0; cipher[i] != '\0'; i++) { 34 | char k; 35 | for (k = 0; k < 64 && sky_base64_map[k] != cipher[i]; k++); 36 | buffer[counts++] = k; 37 | if (counts == 4) { 38 | plain[p++] = (buffer[0] << 2) + (buffer[1] >> 4); 39 | if (buffer[2] != 64) 40 | plain[p++] = (buffer[1] << 4) + (buffer[2] >> 2); 41 | if (buffer[3] != 64) 42 | plain[p++] = (buffer[2] << 6) + buffer[3]; 43 | counts = 0; 44 | } 45 | } 46 | 47 | return plain; 48 | } -------------------------------------------------------------------------------- /src/sky_util_base64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_SKY_UTIL_BASE64_H 20 | #define SKYWALKING_SKY_UTIL_BASE64_H 21 | 22 | char *sky_util_base64_decode(char *cipher); 23 | 24 | #endif //SKYWALKING_SKY_UTIL_BASE64_H 25 | -------------------------------------------------------------------------------- /src/sky_util_php.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include "sky_util_php.h" 19 | 20 | void *sky_util_find_obj_func(const char *obj, const char *name) { 21 | zend_class_entry *ce = zend_hash_str_find_ptr(CG(class_table), obj, strlen(obj)); 22 | if (ce != NULL) { 23 | return zend_hash_str_find_ptr(&ce->function_table, name, strlen(name)); 24 | } 25 | return NULL; 26 | } 27 | 28 | void *sky_util_find_func(const char *name) { 29 | return zend_hash_str_find_ptr(CG(function_table), name, strlen(name)); 30 | } 31 | 32 | void sky_util_json_raw(smart_string *dist, char *key, char *value, size_t value_len) { 33 | sky_util_json_key(dist, key); 34 | smart_string_appendl(dist, value, value_len); 35 | } 36 | 37 | void sky_util_json_raw_ex(smart_string *dist, char *key, char *value, size_t value_len) { 38 | sky_util_json_raw(dist, key, value, value_len); 39 | smart_string_appendc(dist, ','); 40 | } 41 | 42 | void sky_util_json_key(smart_string *dist, char *key) { 43 | smart_string_appendc(dist, '"'); 44 | smart_string_appendl(dist, key, strlen(key)); 45 | smart_string_appendc(dist, '"'); 46 | smart_string_appendc(dist, ':'); 47 | } 48 | 49 | void sky_util_json_int(smart_string *dist, char *key, zend_long num) { 50 | sky_util_json_key(dist, key); 51 | smart_string_append_long(dist, num); 52 | } 53 | 54 | void sky_util_json_int_ex(smart_string *dist, char *key, zend_long num) { 55 | sky_util_json_int(dist, key, num); 56 | smart_string_appendc(dist, ','); 57 | } 58 | 59 | void sky_util_json_str(smart_string *dist, char *key, char *value, size_t value_len) { 60 | sky_util_json_key(dist, key); 61 | smart_string_appendc(dist, '"'); 62 | smart_string_appendl(dist, value, value_len); 63 | smart_string_appendc(dist, '"'); 64 | } 65 | 66 | void sky_util_json_str_ex(smart_string *dist, char *key, char *value, size_t value_len) { 67 | sky_util_json_str(dist, key, value, value_len); 68 | smart_string_appendc(dist, ','); 69 | } 70 | 71 | void sky_util_json_bool(smart_string *dist, char *key, bool value) { 72 | sky_util_json_key(dist, key); 73 | if (value) { 74 | smart_string_appendl(dist, "true", 4); 75 | } else { 76 | smart_string_appendl(dist, "false", 5); 77 | } 78 | } 79 | 80 | void sky_util_json_bool_ex(smart_string *dist, char *key, bool value) { 81 | sky_util_json_bool(dist, key, value); 82 | smart_string_appendc(dist, ','); 83 | } -------------------------------------------------------------------------------- /src/sky_util_php.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef SKYWALKING_SKY_UTIL_PHP_H 19 | #define SKYWALKING_SKY_UTIL_PHP_H 20 | 21 | #include "php.h" 22 | #include "stdbool.h" 23 | 24 | #if PHP_VERSION_ID < 70200 25 | 26 | typedef void (*zif_handler)(INTERNAL_FUNCTION_PARAMETERS); 27 | 28 | #endif 29 | 30 | #include "ext/standard/php_smart_string.h" 31 | 32 | void *sky_util_find_obj_func(const char *obj, const char *name); 33 | 34 | void *sky_util_find_func(const char *name); 35 | 36 | void sky_util_json_raw(smart_string *dist, char *key, char *value, size_t value_len); 37 | 38 | void sky_util_json_raw_ex(smart_string *dist, char *key, char *value, size_t value_len); 39 | 40 | void sky_util_json_key(smart_string *dist, char *key); 41 | 42 | void sky_util_json_int(smart_string *dist, char *key, zend_long num); 43 | 44 | void sky_util_json_int_ex(smart_string *dist, char *key, zend_long num); 45 | 46 | void sky_util_json_str(smart_string *dist, char *key, char *value, size_t value_len); 47 | 48 | void sky_util_json_str_ex(smart_string *dist, char *key, char *value, size_t value_len); 49 | 50 | void sky_util_json_bool(smart_string *dist, char *key, bool value); 51 | 52 | void sky_util_json_bool_ex(smart_string *dist, char *key, bool value); 53 | 54 | #endif //SKYWALKING_SKY_UTIL_PHP_H 55 | -------------------------------------------------------------------------------- /src/sky_utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #include "sky_utils.h" 20 | #include "php_skywalking.h" 21 | #include "zend_variables.h" 22 | 23 | //// protect SKYWALKING_G(segment)'s insert and remove 24 | //static std::mutex segments_mutex; 25 | // 26 | //bool starts_with(const char *pre, const char *str) { 27 | // size_t len_pre = strlen(pre), 28 | // len_str = strlen(str); 29 | // return len_str < len_pre ? false : memcmp(pre, str, len_pre) == 0; 30 | //} 31 | // 32 | //std::string get_page_request_uri() { 33 | // zval *carrier; 34 | // zval *request_uri; 35 | // 36 | // std::string uri; 37 | // 38 | // if (strcasecmp("cli", sapi_module.name) == 0) { 39 | // uri = "cli"; 40 | // } else { 41 | // zend_bool jit_initialization = PG(auto_globals_jit); 42 | // 43 | // if (jit_initialization) { 44 | // zend_string *server_str = zend_string_init("_SERVER", sizeof("_SERVER") - 1, 0); 45 | // zend_is_auto_global(server_str); 46 | // zend_string_release(server_str); 47 | // } 48 | // carrier = zend_hash_str_find(&EG(symbol_table), ZEND_STRL("_SERVER")); 49 | // 50 | // request_uri = zend_hash_str_find(Z_ARRVAL_P(carrier), "REQUEST_URI", sizeof("REQUEST_URI") - 1); 51 | // uri = Z_STRVAL_P(request_uri); 52 | // } 53 | // return uri; 54 | //} 55 | // 56 | //std::string get_page_request_peer() { 57 | // zval *carrier; 58 | // zval *request_host; 59 | // zval *request_port; 60 | // 61 | // std::string peer; 62 | // 63 | // zend_bool jit_initialization = PG(auto_globals_jit); 64 | // 65 | // if (jit_initialization) { 66 | // zend_string *server_str = zend_string_init("_SERVER", sizeof("_SERVER") - 1, 0); 67 | // zend_is_auto_global(server_str); 68 | // zend_string_release(server_str); 69 | // } 70 | // carrier = zend_hash_str_find(&EG(symbol_table), ZEND_STRL("_SERVER")); 71 | // 72 | // request_host = zend_hash_str_find(Z_ARRVAL_P(carrier), "HTTP_HOST", sizeof("HTTP_HOST") - 1); 73 | // request_port = zend_hash_str_find(Z_ARRVAL_P(carrier), "SERVER_PORT", sizeof("SERVER_PORT") - 1); 74 | // if (request_host == nullptr) { 75 | // request_host = zend_hash_str_find(Z_ARRVAL_P(carrier), "SERVER_ADDR", sizeof("SERVER_ADDR") - 1); 76 | // } 77 | // 78 | // if (request_host != nullptr && request_port != nullptr) { 79 | // peer = std::string(Z_STRVAL_P(request_host)) + ":" + Z_STRVAL_P(request_port); 80 | // } 81 | // 82 | // return peer; 83 | //} 84 | // 85 | //zval *sky_read_property(zval *obj, const char *property, int parent) { 86 | // if (Z_TYPE_P(obj) == IS_OBJECT) { 87 | // zend_object *object = obj->value.obj; 88 | // zend_class_entry *ce; 89 | // 90 | // if (parent == 0) { 91 | // ce = object->ce; 92 | // } else { 93 | // ce = object->ce->parent; 94 | // } 95 | // 96 | //#if PHP_VERSION_ID < 80000 97 | // return zend_read_property(ce, obj, property, strlen(property), 0, nullptr); 98 | //#else 99 | // return zend_read_property(ce, object, property, strlen(property), 0, nullptr); 100 | //#endif 101 | // } 102 | // return nullptr; 103 | //} 104 | // 105 | //int64_t sky_find_swoole_fd(zend_execute_data *execute_data) { 106 | // 107 | // if (execute_data->prev_execute_data) { 108 | // uint32_t arg_count = ZEND_CALL_NUM_ARGS(execute_data->prev_execute_data); 109 | // if (arg_count == 2) { 110 | // zval *sw_request = ZEND_CALL_ARG(execute_data->prev_execute_data, 1); 111 | // if (Z_TYPE_P(sw_request) == IS_OBJECT) { 112 | // if (strcmp(ZSTR_VAL(Z_OBJ_P(sw_request)->ce->name), "Swoole\\Http\\Request") == 0) { 113 | // zval *fd = sky_read_property(sw_request, "fd", 0); 114 | // return Z_LVAL_P(fd); 115 | // } 116 | // } 117 | // } 118 | // return sky_find_swoole_fd(execute_data->prev_execute_data); 119 | // } 120 | // 121 | // return -1; 122 | //} 123 | // 124 | //SkyCoreSegment *sky_get_segment(int64_t request_id) { 125 | // if (SKYWALKING_G(segment) == nullptr) { 126 | // return nullptr; 127 | // } 128 | // auto *segments = static_cast *>SKYWALKING_G(segment); 129 | // auto it = segments->find(request_id); 130 | // if (it != segments->end()) { 131 | // return it->second; 132 | // } 133 | // return nullptr; 134 | //} 135 | // 136 | sky_core_segment_t *sky_util_find_segment_idx(zend_execute_data *execute_data, int64_t request_id) { 137 | 138 | if (SKYWALKING_G(segments) == NULL) { 139 | // can't be here, since module_init has assigned a map to SKYWALKING_G(segment) 140 | return NULL; 141 | } 142 | 143 | // auto *segments = static_cast *>SKYWALKING_G(segment); 144 | bool do_search = false; 145 | zend_ulong key = 0; 146 | if (request_id >= 0) { 147 | key = request_id; 148 | do_search = true; 149 | } else { 150 | if (SKYWALKING_G(is_swoole)) { 151 | // int64_t fd = sky_find_swoole_fd(execute_data); 152 | // if (fd > 0) { 153 | // key = fd; 154 | // do_search = true; 155 | // } 156 | } else { 157 | do_search = true; 158 | } 159 | } 160 | 161 | if (do_search) { 162 | zval *segment = zend_hash_index_find(SKYWALKING_G(segments), key); 163 | if (segment) { 164 | sky_core_segment_t *core_segment = (sky_core_segment_t *) Z_PTR_P(segment); 165 | return core_segment; 166 | } 167 | } 168 | 169 | return NULL; 170 | } 171 | 172 | bool starts_with(const char *pre, const char *str) { 173 | size_t pre_len = strlen(pre); 174 | size_t str_len = strlen(str); 175 | return str_len < pre_len ? false : memcmp(pre, str, pre_len) == 0; 176 | } 177 | 178 | int sky_util_call_user_func(const char *name, zval *retval_ptr, uint32_t count, zval params[]) { 179 | zval func; 180 | ZVAL_STRING(&func, name); 181 | int ret = call_user_function(CG(function_table), NULL, &func, retval_ptr, count, params); 182 | zval_dtor(&func); 183 | 184 | for (int i = 0; i < count; i++) { 185 | zval_dtor(¶ms[i]); 186 | } 187 | return ret; 188 | } 189 | 190 | //bool sky_insert_segment(uint64_t request_id, SkyCoreSegment *segment) { 191 | // auto *segments = static_cast *>SKYWALKING_G(segment); 192 | // std::lock_guard lock(segments_mutex); 193 | // 194 | // std::pair::iterator, bool> result; 195 | // result = segments->insert(std::pair(request_id, segment)); 196 | // 197 | // return result.second; 198 | //} 199 | // 200 | //void sky_remove_segment(uint64_t request_id) { 201 | // auto *segments = static_cast *>SKYWALKING_G(segment); 202 | // std::lock_guard lock(segments_mutex); 203 | // 204 | // segments->erase(request_id); 205 | //} 206 | // 207 | //std::string sky_get_class_name(zval *obj) { 208 | // if (Z_TYPE_P(obj) == IS_OBJECT) { 209 | // zend_object *object = obj->value.obj; 210 | // return ZSTR_VAL(object->ce->name); 211 | // } 212 | // return ""; 213 | //} 214 | // 215 | //long getUnixTimeStamp() { 216 | // auto ms = std::chrono::duration_cast( 217 | // std::chrono::system_clock::now().time_since_epoch()); 218 | // return ms.count(); 219 | //} 220 | // 221 | //std::string sky_json_encode(zval *parameter) { 222 | // std::string str; 223 | // smart_str buf = {nullptr}; 224 | // zend_long options = 256; 225 | //#if PHP_VERSION_ID >= 70100 226 | // if (php_json_encode(&buf, parameter, (int) options) != SUCCESS) { 227 | // smart_str_free(&buf); 228 | // return str; 229 | // } 230 | //#else 231 | // php_json_encode(&buf, parameter, (int) options); 232 | //#endif 233 | // smart_str_0(&buf); 234 | // if (buf.s != nullptr) { 235 | // str = std::string(ZSTR_VAL(buf.s)); 236 | // smart_str_free(&buf); 237 | // } 238 | // return str; 239 | //} 240 | -------------------------------------------------------------------------------- /src/sky_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 SkyAPM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | 19 | #ifndef SKYWALKING_SKY_UTILS_H 20 | #define SKYWALKING_SKY_UTILS_H 21 | 22 | #include "php.h" 23 | #include "sky_core_segment.h" 24 | 25 | sky_core_segment_t *sky_util_find_segment_idx(zend_execute_data *execute_data, int64_t request_id); 26 | 27 | bool starts_with(const char *pre, const char *str); 28 | 29 | int sky_util_call_user_func(const char *name, zval *retval_ptr, uint32_t count, zval params[]); 30 | //#include 31 | 32 | //#define SKY_IS_OBJECT(p) p != nullptr && Z_TYPE_P(p) == IS_OBJECT 33 | 34 | //bool starts_with(const char *pre, const char *str); 35 | // 36 | //std::string get_page_request_uri(); 37 | // 38 | //std::string get_page_request_peer(); 39 | // 40 | //zval *sky_read_property(zval *obj, const char *property, int parent); 41 | // 42 | //int64_t sky_find_swoole_fd(zend_execute_data *execute_data); 43 | // 44 | //SkyCoreSegment *sky_get_segment(int64_t request_id); 45 | // 46 | //SkyCoreSegment *sky_get_segment(zend_execute_data *execute_data, int64_t request_id); 47 | // 48 | //bool sky_insert_segment(uint64_t request_id, SkyCoreSegment *segment); 49 | // 50 | //void sky_remove_segment(uint64_t request_id); 51 | // 52 | //std::string sky_get_class_name(zval *obj); 53 | // 54 | //long getUnixTimeStamp(); 55 | // 56 | //std::string sky_json_encode(zval *parameter); 57 | #endif //SKYWALKING_SKY_UTILS_H 58 | -------------------------------------------------------------------------------- /swoole.php: -------------------------------------------------------------------------------- 1 | on("start", function ($server) { 21 | echo "Swoole http server is started at http://127.0.0.1:9501\n"; 22 | }); 23 | 24 | $http->on("request", function ($request, $response) { 25 | $response->header("Content-Type", "text/plain"); 26 | $response->end("Hello World\n"); 27 | }); 28 | 29 | $http->start(); --------------------------------------------------------------------------------