From 8342a2c042b80556923597406b26a5b490d5f475 Mon Sep 17 00:00:00 2001 From: wentao Date: Mon, 29 May 2023 11:03:06 +0800 Subject: [PATCH] first commit --- .asf.yaml | 41 + .gitignore | 57 + .licenserc.yaml | 40 + .rustfmt.toml | 27 + Cargo.lock | 2947 +++++++++++++++++ Cargo.toml | 63 + LICENSE | 201 ++ NOTICE | 5 + README.md | 54 + Vagrantfile | 37 + build.rs | 22 + config.m4 | 80 + dist-material/LICENSE | 594 ++++ dist-material/LICENSE.tpl | 26 + dist-material/NOTICE | 6 + .../licenses/LICENSE-aho-corasick.txt | 21 + .../licenses/LICENSE-async-stream-impl.txt | 51 + .../licenses/LICENSE-async-stream.txt | 51 + dist-material/licenses/LICENSE-axum-core.txt | 7 + dist-material/licenses/LICENSE-axum.txt | 25 + dist-material/licenses/LICENSE-bincode.txt | 21 + dist-material/licenses/LICENSE-bindgen.txt | 29 + dist-material/licenses/LICENSE-bytes.txt | 25 + .../licenses/LICENSE-convert_case.txt | 21 + dist-material/licenses/LICENSE-dashmap.txt | 21 + .../licenses/LICENSE-data-encoding.txt | 22 + .../licenses/LICENSE-derive_more.txt | 21 + .../licenses/LICENSE-errno-dragonfly.txt | 21 + dist-material/licenses/LICENSE-h2.txt | 25 + dist-material/licenses/LICENSE-hostname.txt | 22 + dist-material/licenses/LICENSE-http-body.txt | 25 + dist-material/licenses/LICENSE-hyper.txt | 19 + dist-material/licenses/LICENSE-instant.txt | 27 + dist-material/licenses/LICENSE-libloading.txt | 12 + dist-material/licenses/LICENSE-matches.txt | 25 + dist-material/licenses/LICENSE-matchit.txt | 21 + dist-material/licenses/LICENSE-memchr.txt | 21 + dist-material/licenses/LICENSE-mio.txt | 19 + dist-material/licenses/LICENSE-nom.txt | 20 + .../licenses/LICENSE-nu-ansi-term.txt | 22 + .../licenses/LICENSE-openssl-sys.txt | 25 + dist-material/licenses/LICENSE-overload.txt | 21 + .../licenses/LICENSE-phper-alloc.txt | 127 + .../licenses/LICENSE-phper-build.txt | 127 + .../licenses/LICENSE-phper-macros.txt | 127 + dist-material/licenses/LICENSE-phper-sys.txt | 127 + dist-material/licenses/LICENSE-phper.txt | 127 + .../licenses/LICENSE-redox_syscall.txt | 22 + dist-material/licenses/LICENSE-ring.txt | 204 ++ dist-material/licenses/LICENSE-schannel.txt | 7 + .../licenses/LICENSE-sharded-slab.txt | 19 + dist-material/licenses/LICENSE-slab.txt | 25 + dist-material/licenses/LICENSE-spin.txt | 21 + dist-material/licenses/LICENSE-systemstat.txt | 24 + dist-material/licenses/LICENSE-termcolor.txt | 21 + .../licenses/LICENSE-tokio-macros.txt | 47 + .../licenses/LICENSE-tokio-native-tls.txt | 25 + .../licenses/LICENSE-tokio-stream.txt | 25 + dist-material/licenses/LICENSE-tokio-util.txt | 25 + dist-material/licenses/LICENSE-tokio.txt | 25 + .../licenses/LICENSE-tonic-build.txt | 19 + dist-material/licenses/LICENSE-tonic.txt | 19 + .../licenses/LICENSE-tower-layer.txt | 25 + .../licenses/LICENSE-tower-service.txt | 25 + dist-material/licenses/LICENSE-tower.txt | 25 + .../licenses/LICENSE-tracing-attributes.txt | 25 + .../licenses/LICENSE-tracing-core.txt | 25 + .../licenses/LICENSE-tracing-futures.txt | 25 + .../licenses/LICENSE-tracing-log.txt | 25 + .../licenses/LICENSE-tracing-subscriber.txt | 25 + dist-material/licenses/LICENSE-tracing.txt | 25 + dist-material/licenses/LICENSE-try-lock.txt | 21 + dist-material/licenses/LICENSE-untrusted.txt | 13 + dist-material/licenses/LICENSE-valuable.txt | 25 + dist-material/licenses/LICENSE-want.txt | 20 + dist-material/licenses/LICENSE-webpki.txt | 19 + dist-material/licenses/LICENSE-which.txt | 19 + .../licenses/LICENSE-winapi-util.txt | 21 + dist-material/licenses/LICENSE-winreg.txt | 19 + docker-compose.yml | 53 + docker/Dockerfile | 43 + docs/README.md | 5 + docs/en/configuration/ini-settings.md | 21 + docs/en/contribution/compiling.md | 68 + docs/en/contribution/release-agent.md | 176 + .../setup/service-agent/php-agent/README.md | 111 + .../service-agent/php-agent/Supported-list.md | 21 + docs/menu.yml | 34 + package.tpl.xml | 76 + rust-toolchain.toml | 18 + scripts/Cargo.toml | 34 + scripts/src/command/create_package_xml.rs | 114 + scripts/src/command/mod.rs | 32 + scripts/src/main.rs | 49 + src/channel.rs | 95 + src/component.rs | 27 + src/context.rs | 72 + src/errors.rs | 46 + src/execute.rs | 326 ++ src/lib.rs | 180 + src/module.rs | 261 ++ src/plugin/mod.rs | 76 + src/plugin/plugin_amqplib.rs | 177 + src/plugin/plugin_curl.rs | 461 +++ src/plugin/plugin_memcached.rs | 384 +++ src/plugin/plugin_mysqli.rs | 180 + src/plugin/plugin_pdo.rs | 331 ++ src/plugin/plugin_predis.rs | 280 ++ src/plugin/plugin_redis.rs | 383 +++ src/plugin/plugin_swoole.rs | 136 + src/request.rs | 333 ++ src/tag.rs | 52 + src/util.rs | 98 + src/worker.rs | 318 ++ tests/common/mod.rs | 358 ++ tests/conf/php-fpm.1.conf | 35 + tests/conf/php-fpm.2.conf | 35 + tests/conf/php.ini | 236 ++ tests/data/expected_context.yaml | 1554 +++++++++ tests/e2e.rs | 220 ++ tests/php/composer.json | 18 + tests/php/composer.lock | 1054 ++++++ tests/php/fpm/curl-multi.enter.php | 114 + tests/php/fpm/curl.enter.php | 82 + tests/php/fpm/curl.test.php | 26 + tests/php/fpm/guzzle.php | 31 + tests/php/fpm/index.php | 18 + tests/php/fpm/memcached.php | 42 + tests/php/fpm/mysqli.php | 35 + tests/php/fpm/pdo.php | 53 + tests/php/fpm/predis.php | 32 + tests/php/fpm/rabbitmq.php | 49 + tests/php/fpm/redis.fail.php | 30 + tests/php/fpm/redis.succ.php | 32 + tests/php/swoole/main.1.php | 82 + tests/php/swoole/main.2.php | 115 + 136 files changed, 15707 insertions(+) create mode 100644 .asf.yaml create mode 100644 .gitignore create mode 100644 .licenserc.yaml create mode 100644 .rustfmt.toml create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 NOTICE create mode 100644 README.md create mode 100644 Vagrantfile create mode 100644 build.rs create mode 100644 config.m4 create mode 100644 dist-material/LICENSE create mode 100644 dist-material/LICENSE.tpl create mode 100644 dist-material/NOTICE create mode 100644 dist-material/licenses/LICENSE-aho-corasick.txt create mode 100644 dist-material/licenses/LICENSE-async-stream-impl.txt create mode 100644 dist-material/licenses/LICENSE-async-stream.txt create mode 100644 dist-material/licenses/LICENSE-axum-core.txt create mode 100644 dist-material/licenses/LICENSE-axum.txt create mode 100644 dist-material/licenses/LICENSE-bincode.txt create mode 100644 dist-material/licenses/LICENSE-bindgen.txt create mode 100644 dist-material/licenses/LICENSE-bytes.txt create mode 100644 dist-material/licenses/LICENSE-convert_case.txt create mode 100644 dist-material/licenses/LICENSE-dashmap.txt create mode 100644 dist-material/licenses/LICENSE-data-encoding.txt create mode 100644 dist-material/licenses/LICENSE-derive_more.txt create mode 100644 dist-material/licenses/LICENSE-errno-dragonfly.txt create mode 100644 dist-material/licenses/LICENSE-h2.txt create mode 100644 dist-material/licenses/LICENSE-hostname.txt create mode 100644 dist-material/licenses/LICENSE-http-body.txt create mode 100644 dist-material/licenses/LICENSE-hyper.txt create mode 100644 dist-material/licenses/LICENSE-instant.txt create mode 100644 dist-material/licenses/LICENSE-libloading.txt create mode 100644 dist-material/licenses/LICENSE-matches.txt create mode 100644 dist-material/licenses/LICENSE-matchit.txt create mode 100644 dist-material/licenses/LICENSE-memchr.txt create mode 100644 dist-material/licenses/LICENSE-mio.txt create mode 100644 dist-material/licenses/LICENSE-nom.txt create mode 100644 dist-material/licenses/LICENSE-nu-ansi-term.txt create mode 100644 dist-material/licenses/LICENSE-openssl-sys.txt create mode 100644 dist-material/licenses/LICENSE-overload.txt create mode 100644 dist-material/licenses/LICENSE-phper-alloc.txt create mode 100644 dist-material/licenses/LICENSE-phper-build.txt create mode 100644 dist-material/licenses/LICENSE-phper-macros.txt create mode 100644 dist-material/licenses/LICENSE-phper-sys.txt create mode 100644 dist-material/licenses/LICENSE-phper.txt create mode 100644 dist-material/licenses/LICENSE-redox_syscall.txt create mode 100644 dist-material/licenses/LICENSE-ring.txt create mode 100644 dist-material/licenses/LICENSE-schannel.txt create mode 100644 dist-material/licenses/LICENSE-sharded-slab.txt create mode 100644 dist-material/licenses/LICENSE-slab.txt create mode 100644 dist-material/licenses/LICENSE-spin.txt create mode 100644 dist-material/licenses/LICENSE-systemstat.txt create mode 100644 dist-material/licenses/LICENSE-termcolor.txt create mode 100644 dist-material/licenses/LICENSE-tokio-macros.txt create mode 100644 dist-material/licenses/LICENSE-tokio-native-tls.txt create mode 100644 dist-material/licenses/LICENSE-tokio-stream.txt create mode 100644 dist-material/licenses/LICENSE-tokio-util.txt create mode 100644 dist-material/licenses/LICENSE-tokio.txt create mode 100644 dist-material/licenses/LICENSE-tonic-build.txt create mode 100644 dist-material/licenses/LICENSE-tonic.txt create mode 100644 dist-material/licenses/LICENSE-tower-layer.txt create mode 100644 dist-material/licenses/LICENSE-tower-service.txt create mode 100644 dist-material/licenses/LICENSE-tower.txt create mode 100644 dist-material/licenses/LICENSE-tracing-attributes.txt create mode 100644 dist-material/licenses/LICENSE-tracing-core.txt create mode 100644 dist-material/licenses/LICENSE-tracing-futures.txt create mode 100644 dist-material/licenses/LICENSE-tracing-log.txt create mode 100644 dist-material/licenses/LICENSE-tracing-subscriber.txt create mode 100644 dist-material/licenses/LICENSE-tracing.txt create mode 100644 dist-material/licenses/LICENSE-try-lock.txt create mode 100644 dist-material/licenses/LICENSE-untrusted.txt create mode 100644 dist-material/licenses/LICENSE-valuable.txt create mode 100644 dist-material/licenses/LICENSE-want.txt create mode 100644 dist-material/licenses/LICENSE-webpki.txt create mode 100644 dist-material/licenses/LICENSE-which.txt create mode 100644 dist-material/licenses/LICENSE-winapi-util.txt create mode 100644 dist-material/licenses/LICENSE-winreg.txt create mode 100644 docker-compose.yml create mode 100644 docker/Dockerfile create mode 100644 docs/README.md create mode 100644 docs/en/configuration/ini-settings.md create mode 100644 docs/en/contribution/compiling.md create mode 100644 docs/en/contribution/release-agent.md create mode 100644 docs/en/setup/service-agent/php-agent/README.md create mode 100644 docs/en/setup/service-agent/php-agent/Supported-list.md create mode 100644 docs/menu.yml create mode 100644 package.tpl.xml create mode 100644 rust-toolchain.toml create mode 100644 scripts/Cargo.toml create mode 100644 scripts/src/command/create_package_xml.rs create mode 100644 scripts/src/command/mod.rs create mode 100644 scripts/src/main.rs create mode 100644 src/channel.rs create mode 100644 src/component.rs create mode 100644 src/context.rs create mode 100644 src/errors.rs create mode 100644 src/execute.rs create mode 100644 src/lib.rs create mode 100644 src/module.rs create mode 100644 src/plugin/mod.rs create mode 100644 src/plugin/plugin_amqplib.rs create mode 100644 src/plugin/plugin_curl.rs create mode 100644 src/plugin/plugin_memcached.rs create mode 100644 src/plugin/plugin_mysqli.rs create mode 100644 src/plugin/plugin_pdo.rs create mode 100644 src/plugin/plugin_predis.rs create mode 100644 src/plugin/plugin_redis.rs create mode 100644 src/plugin/plugin_swoole.rs create mode 100644 src/request.rs create mode 100644 src/tag.rs create mode 100644 src/util.rs create mode 100644 src/worker.rs create mode 100644 tests/common/mod.rs create mode 100644 tests/conf/php-fpm.1.conf create mode 100644 tests/conf/php-fpm.2.conf create mode 100644 tests/conf/php.ini create mode 100644 tests/data/expected_context.yaml create mode 100644 tests/e2e.rs create mode 100644 tests/php/composer.json create mode 100644 tests/php/composer.lock create mode 100644 tests/php/fpm/curl-multi.enter.php create mode 100644 tests/php/fpm/curl.enter.php create mode 100644 tests/php/fpm/curl.test.php create mode 100644 tests/php/fpm/guzzle.php create mode 100644 tests/php/fpm/index.php create mode 100644 tests/php/fpm/memcached.php create mode 100644 tests/php/fpm/mysqli.php create mode 100644 tests/php/fpm/pdo.php create mode 100644 tests/php/fpm/predis.php create mode 100644 tests/php/fpm/rabbitmq.php create mode 100644 tests/php/fpm/redis.fail.php create mode 100644 tests/php/fpm/redis.succ.php create mode 100644 tests/php/swoole/main.1.php create mode 100644 tests/php/swoole/main.2.php diff --git a/.asf.yaml b/.asf.yaml new file mode 100644 index 0000000..8d96edd --- /dev/null +++ b/.asf.yaml @@ -0,0 +1,41 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +github: + description: Apache SkyWalking PHP Agent + homepage: https://skywalking.apache.org/ + labels: + - skywalking + - observability + - apm + - distributed-tracing + - service-mesh + - dapper + - php + enabled_merge_buttons: + squash: true + merge: false + rebase: false + protected_branches: + master: + required_status_checks: + strict: true + contexts: + - license + - pecl-required + - required + required_pull_request_reviews: + dismiss_stale_reviews: true + required_approving_review_count: 1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2c3937b --- /dev/null +++ b/.gitignore @@ -0,0 +1,57 @@ +# Generated by Cargo, will have compiled files and executables. +/target/ +# These are backup files generated by rustfmt. +**/*.rs.bk +# Local Cargo config file. +/.cargo/config.toml +# PHP composer vendor. +/tests/php/vendor/ + +/skywalking_agent-*.tgz +/skywalking_agent-*.tgz.asc +/skywalking_agent-*.tgz.sha512 +/package.xml +/.vagrant + +*.lo +*.la +.libs +acinclude.m4 +aclocal.m4 +autom4te.cache +build +config.guess +config.h +config.h.in +config.h.in~ +config.log +config.nice +config.status +config.sub +configure +configure.ac +configure.in +include +install-sh +libtool +ltmain.sh +Makefile +Makefile.fragments +Makefile.global +Makefile.objects +missing +mkinstalldirs +modules +php_test_results_*.txt +phpt.* +run-test-info.php +run-tests.php +tests/**/*.diff +tests/**/*.out +tests/**/*.exp +tests/**/*.log +tests/**/*.db +tests/**/*.mem +tmp-php.ini +.fleet +.idea diff --git a/.licenserc.yaml b/.licenserc.yaml new file mode 100644 index 0000000..222a72e --- /dev/null +++ b/.licenserc.yaml @@ -0,0 +1,40 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +header: + license: + spdx-id: Apache-2.0 + copyright-owner: Apache Software Foundation + + paths-ignore: + - '**/*.json' + - '**/*.lock' + - '**/*.md' + - '**/.gitignore' + - '**/.gitmodules' + - '.cargo' + - '.idea' + - '.vscode' + - 'LICENSE' + - 'NOTICE' + - 'config.m4' + - 'vendor' + - 'dist-material' + + comment: on-failure + +dependency: + files: + - Cargo.toml diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..7a6424a --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,27 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +fn_params_layout = "Compressed" +format_code_in_doc_comments = true +format_macro_bodies = true +format_macro_matchers = true +format_strings = true +imports_granularity = "Crate" +merge_derives = true +newline_style = "Unix" +normalize_comments = true +reorder_impl_items = true +use_field_init_shorthand = true +wrap_comments = true diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..a1ebc92 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2947 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" +dependencies = [ + "backtrace", +] + +[[package]] +name = "async-stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-trait" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "705339e0e4a9690e2908d2b3d049d85682cf19fbd5782494498fbf7003a6a282" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "axum" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13d8068b6ccb8b34db9de397c7043f91db8b4c66414952c6db944f238c4d3db3" +dependencies = [ + "async-trait", + "axum-core", + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2f958c80c248b34b9a877a643811be8dbca03ca5ba827f2b63baf3a81e5fc4e" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bindgen" +version = "0.63.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36d860121800b2a9a94f9b5604b332d5cffb234ce17609ea479d723dbc9d3885" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bstr" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45ea9b00a7b3f2988e9a65ad3917e62123c38dba709b666506207be96d1790b" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" + +[[package]] +name = "bytes" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" + +[[package]] +name = "bytesize" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c58ec36aac5066d5ca17df51b3e70279f5670a72102f5752cb7e7c856adfc70" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "time 0.1.45", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "chrono-tz" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58549f1842da3080ce63002102d5bc954c7bc843d4f47818e642abdc36253552" +dependencies = [ + "chrono", + "chrono-tz-build", + "phf", +] + +[[package]] +name = "chrono-tz-build" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db058d493fb2f65f41861bfed7e3fe6335264a9f0f92710cab5bdf01fef09069" +dependencies = [ + "parse-zoneinfo", + "phf", + "phf_codegen", +] + +[[package]] +name = "clang-sys" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d7ae14b20b94cb02149ed21a86c423859cbe18dc7ed69845cace50e52b40a5" +dependencies = [ + "bitflags", + "clap_derive", + "clap_lex", + "is-terminal", + "once_cell", + "strsim", + "termcolor", +] + +[[package]] +name = "clap_derive" +version = "4.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44bec8e5c9d09e439c4335b1af0abaab56dcf3b94999a936e1bb47b9134288f0" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cxx" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d1075c37807dcf850c379432f0df05ba52cc30f279c5cfc43cc221ce7f8579" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5044281f61b27bc598f2f6647d480aed48d2bf52d6eb0b627d84c0361b17aa70" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61b50bc93ba22c27b0d31128d2d130a0a6b3d267ae27ef7e4fae2167dfe8781c" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e61fda7e62115119469c7b3591fd913ecca96fb766cfd3f2e2502ab7bc87a5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dashmap" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" +dependencies = [ + "cfg-if", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "data-encoding" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb" + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn", +] + +[[package]] +name = "deunicode" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690" + +[[package]] +name = "digest" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "encoding_rs" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum-as-inner" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fastcgi-client" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55a27f39a5870033a855957f11281192a078b70bd4c403c887eac619b50473ea" +dependencies = [ + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "fastrand" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +dependencies = [ + "instant", +] + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd" + +[[package]] +name = "futures-io" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91" + +[[package]] +name = "futures-macro" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2" + +[[package]] +name = "futures-task" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879" + +[[package]] +name = "futures-util" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "gimli" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "globset" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + +[[package]] +name = "globwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +dependencies = [ + "bitflags", + "ignore", + "walkdir", +] + +[[package]] +name = "h2" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b91535aa35fea1523ad1b86cb6b53c28e0ae566ba4a460f4457e936cad7c6f" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "humansize" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" +dependencies = [ + "libm", +] + +[[package]] +name = "hyper" +version = "0.14.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "ignore" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a05705bc64e0b66a806c3740bd6578ea66051b157ec42dc219c785cbf185aef3" +dependencies = [ + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" +dependencies = [ + "libc", + "windows-sys 0.45.0", +] + +[[package]] +name = "ipconfig" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd302af1b90f2463a98fa5ad469fc212c8e3175a41c3068601bfa2727591c5be" +dependencies = [ + "socket2", + "widestring", + "winapi", + "winreg", +] + +[[package]] +name = "ipnet" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" + +[[package]] +name = "is-terminal" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189" +dependencies = [ + "hermit-abi", + "io-lifetimes", + "rustix", + "windows-sys 0.42.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" + +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libm" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" + +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + +[[package]] +name = "matchit" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.42.0", +] + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "nom" +version = "7.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5507769c4919c998e69e49c839d9dc6e693ede4cc4290d6ad8b41d4f09c548c" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d864c91689fdc196779b98dba0aceac6118594c2df6ee5d943eb6a8df4d107a" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "openssl" +version = "0.10.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "518915b97df115dd36109bfa429a48b8f737bd05508cf9588977b599648926d2" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666416d899cf077260dac8698d60a60b435a46d57e82acb1be3d0dad87284e5b" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "os_str_bytes" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys 0.42.0", +] + +[[package]] +name = "parse-zoneinfo" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" +dependencies = [ + "regex", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "pest" +version = "2.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cbd939b234e95d72bc393d51788aec68aeeb5d51e748ca08ff3aad58cb722f7" +dependencies = [ + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a81186863f3d0a27340815be8f2078dd8050b14cd71913db9fbda795e5f707d7" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75a1ef20bf3193c15ac345acb32e26b3dc3223aff4d77ae4fc5359567683796b" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e3b284b1f13a20dc5ebc90aff59a51b8d7137c221131b52a7260c08cbc1cc80" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + +[[package]] +name = "petgraph" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", + "uncased", +] + +[[package]] +name = "phper" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bca4911bd7afcc27563c8c71fee774200efe3466b91ef267eed9fe786465a56c" +dependencies = [ + "derive_more", + "indexmap", + "once_cell", + "phper-alloc", + "phper-build", + "phper-macros", + "phper-sys", + "thiserror", +] + +[[package]] +name = "phper-alloc" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e459b21c04d72e5f9ae95483e49165acfeb5c24fff2b9021118107be1b963dfe" +dependencies = [ + "phper-build", + "phper-sys", +] + +[[package]] +name = "phper-build" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88285cabb005695e8fb009926d1e54b8be7d0b293b8eb2c3271dd75cce706ad0" +dependencies = [ + "phper-sys", +] + +[[package]] +name = "phper-macros" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7058f7a91da7bac48e076d8c985c5f264c062dee9b1fc06f4439f67426594168" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phper-sys" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb326355ebedca7f81fb65be596365f0b5f52d8a85197047ff4186c97f68fde9" +dependencies = [ + "bindgen", + "cc", +] + +[[package]] +name = "pin-project" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + +[[package]] +name = "portable-atomic" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26f6a7b87c2e435a3241addceeeff740ff8b7e76b74c13bf9acb17fa454ea00b" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "prettyplease" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97e3215779627f01ee256d2fad52f3d95e8e1c11e9fc6fd08f7cd455d5d5c78" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f8ad728fb08fe212df3c05169e940fbb6d9d16a877ddde14644a983ba2012e" +dependencies = [ + "bytes", + "heck", + "itertools", + "lazy_static", + "log", + "multimap", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn", + "tempfile", + "which", +] + +[[package]] +name = "prost-derive" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e0526209433e96d83d750dd81a99118edbc55739e7e61a46764fd2ad537788" +dependencies = [ + "bytes", + "prost", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + +[[package]] +name = "reqwest" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" +dependencies = [ + "base64 0.21.0", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tokio-util", + "tower-service", + "trust-dns-resolver", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "winreg", +] + +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.36.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.45.0", +] + +[[package]] +name = "rustls" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +dependencies = [ + "base64 0.21.0", +] + +[[package]] +name = "rustversion" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" + +[[package]] +name = "ryu" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +dependencies = [ + "windows-sys 0.42.0", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "scratch" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" + +[[package]] +name = "scripts" +version = "0.0.0" +dependencies = [ + "anyhow", + "chrono", + "clap", + "serde", + "tera", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "security-framework" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" + +[[package]] +name = "serde" +version = "1.0.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71f2b4817415c6d4210bfe1c7bfcf4801b2d904cb4d0e1a8fdb651013c9e86b8" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d071a94a3fac4aff69d023a7f411e33f40f3483f8c5190b1953822b6b76d7630" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_path_to_error" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b04f22b563c91331a10074bda3dd5492e3cc39d56bd557e91c0af42b6c7341" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + +[[package]] +name = "skywalking" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df0d94ba57de62d094dc1c00f3b20e1528c66c5b267df7d35da250982e3670b" +dependencies = [ + "base64 0.13.1", + "bytes", + "cfg-if", + "futures-core", + "futures-util", + "hostname", + "once_cell", + "parking_lot", + "portable-atomic", + "prost", + "prost-derive", + "serde", + "systemstat", + "thiserror", + "tokio", + "tokio-stream", + "tonic", + "tonic-build", + "tracing", + "uuid", +] + +[[package]] +name = "skywalking-php" +version = "0.5.0" +dependencies = [ + "anyhow", + "axum", + "bincode", + "chrono", + "dashmap", + "fastcgi-client", + "futures-util", + "hostname", + "libc", + "once_cell", + "phper", + "prost", + "reqwest", + "serde_json", + "skywalking", + "systemstat", + "thiserror", + "tokio", + "tokio-stream", + "tonic", + "tracing", + "tracing-subscriber", + "url", +] + +[[package]] +name = "slab" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] + +[[package]] +name = "slug" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373" +dependencies = [ + "deunicode", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "socket2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" + +[[package]] +name = "systemstat" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a24aec24a9312c83999a28e3ef9db7e2afd5c64bf47725b758cdc1cafd5b0bd2" +dependencies = [ + "bytesize", + "lazy_static", + "libc", + "nom", + "time 0.3.17", + "winapi", +] + +[[package]] +name = "tempfile" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys 0.42.0", +] + +[[package]] +name = "tera" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27df4164dd125228af4c90c9799a29740e39151767d579f3fc711491054a0378" +dependencies = [ + "chrono", + "chrono-tz", + "globwalk", + "humansize", + "lazy_static", + "percent-encoding", + "pest", + "pest_derive", + "rand", + "regex", + "serde", + "serde_json", + "slug", + "thread_local", + "unic-segment", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "time" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +dependencies = [ + "serde", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tokio" +version = "1.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.45.0", +] + +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-macros" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls", + "tokio", + "webpki", +] + +[[package]] +name = "tokio-stream" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tonic" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.13.1", + "bytes", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "prost-derive", + "rustls-pemfile", + "tokio", + "tokio-rustls", + "tokio-stream", + "tokio-util", + "tower", + "tower-layer", + "tower-service", + "tracing", + "tracing-futures", +] + +[[package]] +name = "tonic-build" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf5e9b9c0f7e0a7c027dcfaba7b2c60816c7049171f679d99ee2ff65d0de8c4" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "quote", + "syn", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "trust-dns-proto" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f7f83d1e4a0e4358ac54c5c3681e5d7da5efc5a7a632c90bb6d6669ddd9bc26" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.2.3", + "ipnet", + "lazy_static", + "rand", + "smallvec", + "thiserror", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "trust-dns-resolver" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aff21aa4dcefb0a1afbfac26deb0adc93888c7d295fb63ab273ef276ba2b7cfe" +dependencies = [ + "cfg-if", + "futures-util", + "ipconfig", + "lazy_static", + "lru-cache", + "parking_lot", + "resolv-conf", + "smallvec", + "thiserror", + "tokio", + "tracing", + "trust-dns-proto", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "ucd-trie" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" + +[[package]] +name = "uncased" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622" +dependencies = [ + "version_check", +] + +[[package]] +name = "unic-char-property" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +dependencies = [ + "unic-char-range", +] + +[[package]] +name = "unic-char-range" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" + +[[package]] +name = "unic-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" + +[[package]] +name = "unic-segment" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23" +dependencies = [ + "unic-ucd-segment", +] + +[[package]] +name = "unic-ucd-segment" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-version" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" +dependencies = [ + "unic-common", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna 0.3.0", + "percent-encoding", +] + +[[package]] +name = "uuid" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c" +dependencies = [ + "getrandom", + "serde", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + +[[package]] +name = "wasm-streams" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bbae3363c08332cadccd13b67db371814cd214c2524020932f0804b8cf7c078" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "web-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "which" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +dependencies = [ + "either", + "libc", + "once_cell", +] + +[[package]] +name = "widestring" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..e379b9c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,63 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +[workspace] +members = [ + ".", + "scripts", +] + +[package] +name = "skywalking-php" +version = "0.5.0" +authors = ["Apache Software Foundation", "jmjoy ", "Yanlong He "] +description = "Apache SkyWalking PHP Agent." +edition = "2021" +rust-version = "1.65" +repository = "https://github.com/apache/skywalking-php" +license = "Apache-2.0" +readme = "README.md" +publish = false + +[lib] +name = "skywalking_agent" +crate-type = ["lib", "cdylib"] + +[dependencies] +anyhow = { version = "1.0.69", features = ["backtrace"] } +bincode = "1.3.3" +chrono = "0.4.24" +dashmap = "5.4.0" +futures-util = "0.3.27" +hostname = "0.3.1" +libc = "0.2.140" +once_cell = "1.17.1" +phper = "0.11.0" +prost = "0.11.8" +serde_json = { version = "1.0.94", features = ["preserve_order"] } +skywalking = { version = "0.6.0", features = ["management"] } +systemstat = "0.2.3" +thiserror = "1.0.39" +tokio = { version = "1.26.0", features = ["full"] } +tokio-stream = "0.1.12" +tonic = { version = "0.8.3", features = ["tls"] } +tracing = { version = "0.1.37", features = ["attributes"] } +tracing-subscriber = "0.3.16" +url = "2.3.1" + +[dev-dependencies] +axum = "0.6.11" +fastcgi-client = "0.8.0" +reqwest = { version = "0.11.14", features = ["trust-dns", "json", "stream"] } diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9c8f3ea --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..c68c699 --- /dev/null +++ b/NOTICE @@ -0,0 +1,5 @@ +Apache SkyWalking +Copyright 2017-2023 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). diff --git a/README.md b/README.md new file mode 100644 index 0000000..e0087f6 --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +# Apache SkyWalking PHP Agent + +Sky Walking logo + +**SkyWalking PHP** The PHP Agent for Apache SkyWalking, which provides the native tracing abilities for PHP project. + +**SkyWalking** an APM(application performance monitor) system, especially designed for +microservices, cloud native and container-based (Docker, Kubernetes, Mesos) architectures. + +[![GitHub stars](https://img.shields.io/github/stars/apache/skywalking-php.svg?style=for-the-badge&label=Stars&logo=github)](https://github.com/apache/skywalking-php) +[![Twitter Follow](https://img.shields.io/twitter/follow/asfskywalking.svg?style=for-the-badge&label=Follow&logo=twitter)](https://twitter.com/AsfSkyWalking) + +## Documentation + +* [Official documentation](https://skywalking.apache.org/docs/#PHPAgent) + +## How to create issue? + +Submit an [GitHub Issue](https://github.com/apache/skywalking/issues/new/choose) in the Apache Skywalking repository, by using [PHP] as title prefix. + +## Installation Requirements + +SkyWalking PHP Agent requires SkyWalking 8.4+ and PHP 7.2+ + +## Support List + +* PHP-FPM Ecosystem + * [x] [cURL](https://www.php.net/manual/en/book.curl.php#book.curl) + * [x] [PDO](https://www.php.net/manual/en/book.pdo.php) + * [x] [MySQL Improved](https://www.php.net/manual/en/book.mysqli.php) + * [x] [Memcached](https://www.php.net/manual/en/book.memcached.php) + * [x] [phpredis](https://github.com/phpredis/phpredis) + * [ ] [php-amqp](https://github.com/php-amqp/php-amqp) + * [ ] [php-rdkafka](https://github.com/arnaud-lb/php-rdkafka) + * [x] [predis](https://github.com/predis/predis) + * [x] [php-amqplib](https://github.com/php-amqplib/php-amqplib) for Message Queuing Producer + +* Swoole Ecosystem + + *The components of the PHP-FPM ecosystem can also be used in Swoole, wether the flag `SWOOLE_HOOK_ALL` is enabled or not.* + +## Contact Us + +* Mail list: **dev@skywalking.apache.org**. Mail to `dev-subscribe@skywalking.apache.org`, follow the reply to subscribe the mail list. +* Join `skywalking` channel at [Apache Slack](http://s.apache.org/slack-invite). If the link is not working, find the latest one at [Apache INFRA WIKI](https://cwiki.apache.org/confluence/display/INFRA/Slack+Guest+Invites). +* Twitter, [ASFSkyWalking](https://twitter.com/AsfSkyWalking) + +## Stargazers over time + +[![Stargazers over time](https://starchart.cc/apache/skywalking-php.svg)](https://starchart.cc/apache/skywalking-php) + +## License + +[Apache 2.0](LICENSE) diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000..e826de0 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,37 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +Vagrant.configure("2") do |config| + config.vm.box = "generic/alpine316" + config.vm.box_version = "4.1.10" + config.vm.box_check_update = false + + config.vm.network "forwarded_port", guest: 19876, host: 19876 + config.vm.network "forwarded_port", guest: 12800, host: 12800 + config.vm.network "forwarded_port", guest: 3306, host: 3306 + config.vm.network "forwarded_port", guest: 6379, host: 6379 + config.vm.network "forwarded_port", guest: 11211, host: 11211 + config.vm.network "forwarded_port", guest: 5672, host: 5672 + + config.vm.synced_folder ".", "/vagrant" + + config.vm.provision "shell", inline: <<-SHELL + apk add --no-cache docker docker-cli-compose + service docker restart + sleep 3 + cd /vagrant + sudo docker compose up -d + SHELL +end diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..dd029df --- /dev/null +++ b/build.rs @@ -0,0 +1,22 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +fn main() { + #[cfg(target_os = "macos")] + { + println!("cargo:rustc-link-arg=-undefined"); + println!("cargo:rustc-link-arg=dynamic_lookup"); + } +} diff --git a/config.m4 b/config.m4 new file mode 100644 index 0000000..b4f9560 --- /dev/null +++ b/config.m4 @@ -0,0 +1,80 @@ +dnl Licensed to the Apache Software Foundation (ASF) under one or more +dnl contributor license agreements. See the NOTICE file distributed with +dnl this work for additional information regarding copyright ownership. +dnl The ASF licenses this file to You under the Apache License, Version 2.0 +dnl (the "License"); you may not use this file except in compliance with +dnl the License. You may obtain a copy of the License at +dnl +dnl http://www.apache.org/licenses/LICENSE-2.0 +dnl +dnl Unless required by applicable law or agreed to in writing, software +dnl distributed under the License is distributed on an "AS IS" BASIS, +dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +dnl See the License for the specific language governing permissions and +dnl limitations under the License. + +PHP_ARG_ENABLE([skywalking_agent], + [whether to enable skywalking_agent support], + [AS_HELP_STRING([--enable-skywalking_agent], + [Enable skywalking_agent support])], + [no]) + +PHP_ARG_ENABLE([cargo_debug], [whether to enable cargo debug mode], +[ --enable-cargo-debug Enable cargo debug], no, no) + +if test "$PHP_THREAD_SAFETY" == "yes"; then + AC_MSG_ERROR([skywalking_agent does not support ZTS]) +fi + +if test "$PHP_SKYWALKING_AGENT" != "no"; then + AC_PATH_PROG(CARGO, cargo, no) + if ! test -x "$CARGO"; then + AC_MSG_ERROR([cargo command missing, please reinstall the cargo distribution]) + fi + + AC_PATH_PROG(PROTOC, protoc, no) + if ! test -x "$PROTOC"; then + AC_MSG_ERROR([protoc command missing, please reinstall the protoc distribution]) + fi + + AC_DEFINE(HAVE_SKYWALKING_AGENT, 1, [ Have skywalking_agent support ]) + + PHP_NEW_EXTENSION(skywalking_agent, [ ], $ext_shared) + + CARGO_MODE_FLAGS="--release" + CARGO_MODE_DIR="release" + + if test "$PHP_CARGO_DEBUG" != "no"; then + CARGO_MODE_FLAGS="" + CARGO_MODE_DIR="debug" + fi + + cat >>Makefile.objects<< EOF +all: cargo_build + +clean: cargo_clean + +cargo_build: + PHP_CONFIG=$PHP_PHP_CONFIG cargo build $CARGO_MODE_FLAGS + if [[ -f ./target/$CARGO_MODE_DIR/libskywalking_agent.dylib ]] ; then \\ + cp ./target/$CARGO_MODE_DIR/libskywalking_agent.dylib ./modules/skywalking_agent.so ; fi + if [[ -f ./target/$CARGO_MODE_DIR/libskywalking_agent.so ]] ; then \\ + cp ./target/$CARGO_MODE_DIR/libskywalking_agent.so ./modules/skywalking_agent.so ; fi + +cargo_clean: + cargo clean + +.PHONY: cargo_build cargo_clean +EOF + + AC_CONFIG_LINKS([ \ + .rustfmt.toml:.rustfmt.toml \ + Cargo.lock:Cargo.lock \ + Cargo.toml:Cargo.toml \ + build.rs:build.rs \ + docker-compose.yml:docker-compose.yml \ + scripts:scripts \ + src:src \ + tests:tests \ + ]) +fi diff --git a/dist-material/LICENSE b/dist-material/LICENSE new file mode 100644 index 0000000..9d3e908 --- /dev/null +++ b/dist-material/LICENSE @@ -0,0 +1,594 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + +======================================================================= +Apache SkyWalking Subcomponents: + +The Apache SkyWalking project contains subcomponents with separate copyright +notices and license terms. Your use of the source code for the these +subcomponents is subject to the terms and conditions of the following +licenses. +======================================================================== + + +======================================================================== +(Apache-2.0 OR MIT) AND BSD-3-Clause licenses +======================================================================== +The following components are provided under the (Apache-2.0 OR MIT) AND BSD-3-Clause License. See project link for details. +The text of each license is also included in licenses/LICENSE-[project].txt. + + https://crates.io/crates/encoding_rs/0.8.31 0.8.31 (Apache-2.0 OR MIT) AND BSD-3-Clause + +======================================================================== +(MIT OR Apache-2.0) AND Unicode-DFS-2016 licenses +======================================================================== +The following components are provided under the (MIT OR Apache-2.0) AND Unicode-DFS-2016 License. See project link for details. +The text of each license is also included in licenses/LICENSE-[project].txt. + + https://crates.io/crates/unicode-ident/1.0.6 1.0.6 (MIT OR Apache-2.0) AND Unicode-DFS-2016 + +======================================================================== +0BSD OR Apache-2.0 OR MIT licenses +======================================================================== +The following components are provided under the 0BSD OR Apache-2.0 OR MIT License. See project link for details. +The text of each license is also included in licenses/LICENSE-[project].txt. + + https://crates.io/crates/adler/1.0.2 1.0.2 0BSD OR Apache-2.0 OR MIT + +======================================================================== +Apache-2.0 licenses +======================================================================== +The following components are provided under the Apache-2.0 License. See project link for details. +The text of each license is the standard Apache 2.0 license. + https://crates.io/crates/bytesize/1.1.0 1.1.0 Apache-2.0 + https://crates.io/crates/clang-sys/1.4.0 1.4.0 Apache-2.0 + https://crates.io/crates/codespan-reporting/0.11.1 0.11.1 Apache-2.0 + https://crates.io/crates/fastcgi-client/0.8.0 0.8.0 Apache-2.0 + https://crates.io/crates/openssl/0.10.48 0.10.48 Apache-2.0 + https://crates.io/crates/prost/0.11.8 0.11.8 Apache-2.0 + https://crates.io/crates/prost-build/0.11.6 0.11.6 Apache-2.0 + https://crates.io/crates/prost-derive/0.11.8 0.11.8 Apache-2.0 + https://crates.io/crates/prost-types/0.11.6 0.11.6 Apache-2.0 + https://crates.io/crates/scripts/0.0.0 0.0.0 Apache-2.0 + https://crates.io/crates/skywalking/0.6.0 0.6.0 Apache-2.0 + https://crates.io/crates/skywalking-php/0.5.0 0.5.0 Apache-2.0 + https://crates.io/crates/sync_wrapper/0.1.1 0.1.1 Apache-2.0 + +======================================================================== +Apache-2.0 OR Apache-2.0 WITH LLVM-exception OR MIT licenses +======================================================================== +The following components are provided under the Apache-2.0 OR Apache-2.0 WITH LLVM-exception OR MIT License. See project link for details. +The text of each license is also included in licenses/LICENSE-[project].txt. + + https://crates.io/crates/io-lifetimes/1.0.5 1.0.5 Apache-2.0 OR Apache-2.0 WITH LLVM-exception OR MIT + https://crates.io/crates/linux-raw-sys/0.1.4 0.1.4 Apache-2.0 OR Apache-2.0 WITH LLVM-exception OR MIT + https://crates.io/crates/rustix/0.36.8 0.36.8 Apache-2.0 OR Apache-2.0 WITH LLVM-exception OR MIT + https://crates.io/crates/wasi/0.10.0+wasi-snapshot-preview1 0.10.0+wasi-snapshot-preview1 Apache-2.0 OR Apache-2.0 WITH LLVM-exception OR MIT + https://crates.io/crates/wasi/0.11.0+wasi-snapshot-preview1 0.11.0+wasi-snapshot-preview1 Apache-2.0 OR Apache-2.0 WITH LLVM-exception OR MIT + +======================================================================== +Apache-2.0 OR BSL-1.0 licenses +======================================================================== +The following components are provided under the Apache-2.0 OR BSL-1.0 License. See project link for details. +The text of each license is also included in licenses/LICENSE-[project].txt. + + https://crates.io/crates/ryu/1.0.12 1.0.12 Apache-2.0 OR BSL-1.0 + +======================================================================== +Apache-2.0 OR ISC OR MIT licenses +======================================================================== +The following components are provided under the Apache-2.0 OR ISC OR MIT License. See project link for details. +The text of each license is also included in licenses/LICENSE-[project].txt. + + https://crates.io/crates/rustls/0.20.8 0.20.8 Apache-2.0 OR ISC OR MIT + https://crates.io/crates/rustls-pemfile/1.0.2 1.0.2 Apache-2.0 OR ISC OR MIT + https://crates.io/crates/sct/0.7.0 0.7.0 Apache-2.0 OR ISC OR MIT + +======================================================================== +Apache-2.0 OR MIT licenses +======================================================================== +The following components are provided under the Apache-2.0 OR MIT License. See project link for details. +The text of each license is also included in licenses/LICENSE-[project].txt. + + https://crates.io/crates/addr2line/0.19.0 0.19.0 Apache-2.0 OR MIT + https://crates.io/crates/android_system_properties/0.1.5 0.1.5 Apache-2.0 OR MIT + https://crates.io/crates/anyhow/1.0.69 1.0.69 Apache-2.0 OR MIT + https://crates.io/crates/async-trait/0.1.61 0.1.61 Apache-2.0 OR MIT + https://crates.io/crates/autocfg/1.1.0 1.1.0 Apache-2.0 OR MIT + https://crates.io/crates/backtrace/0.3.67 0.3.67 Apache-2.0 OR MIT + https://crates.io/crates/base64/0.13.1 0.13.1 Apache-2.0 OR MIT + https://crates.io/crates/base64/0.21.0 0.21.0 Apache-2.0 OR MIT + https://crates.io/crates/bitflags/1.3.2 1.3.2 Apache-2.0 OR MIT + https://crates.io/crates/block-buffer/0.10.3 0.10.3 Apache-2.0 OR MIT + https://crates.io/crates/bstr/1.1.0 1.1.0 Apache-2.0 OR MIT + https://crates.io/crates/bumpalo/3.11.1 3.11.1 Apache-2.0 OR MIT + https://crates.io/crates/cc/1.0.79 1.0.79 Apache-2.0 OR MIT + https://crates.io/crates/cexpr/0.6.0 0.6.0 Apache-2.0 OR MIT + https://crates.io/crates/cfg-if/1.0.0 1.0.0 Apache-2.0 OR MIT + https://crates.io/crates/chrono/0.4.24 0.4.24 Apache-2.0 OR MIT + https://crates.io/crates/chrono-tz/0.6.1 0.6.1 Apache-2.0 OR MIT + https://crates.io/crates/chrono-tz-build/0.0.2 0.0.2 Apache-2.0 OR MIT + https://crates.io/crates/clap/4.1.8 4.1.8 Apache-2.0 OR MIT + https://crates.io/crates/clap_derive/4.1.8 4.1.8 Apache-2.0 OR MIT + https://crates.io/crates/clap_lex/0.3.0 0.3.0 Apache-2.0 OR MIT + https://crates.io/crates/core-foundation/0.9.3 0.9.3 Apache-2.0 OR MIT + https://crates.io/crates/core-foundation-sys/0.8.3 0.8.3 Apache-2.0 OR MIT + https://crates.io/crates/cpufeatures/0.2.5 0.2.5 Apache-2.0 OR MIT + https://crates.io/crates/crypto-common/0.1.6 0.1.6 Apache-2.0 OR MIT + https://crates.io/crates/cxx/1.0.86 1.0.86 Apache-2.0 OR MIT + https://crates.io/crates/cxx-build/1.0.86 1.0.86 Apache-2.0 OR MIT + https://crates.io/crates/cxxbridge-flags/1.0.86 1.0.86 Apache-2.0 OR MIT + https://crates.io/crates/cxxbridge-macro/1.0.86 1.0.86 Apache-2.0 OR MIT + https://crates.io/crates/digest/0.10.6 0.10.6 Apache-2.0 OR MIT + https://crates.io/crates/either/1.8.1 1.8.1 Apache-2.0 OR MIT + https://crates.io/crates/enum-as-inner/0.5.1 0.5.1 Apache-2.0 OR MIT + https://crates.io/crates/errno/0.2.8 0.2.8 Apache-2.0 OR MIT + https://crates.io/crates/fastrand/1.8.0 1.8.0 Apache-2.0 OR MIT + https://crates.io/crates/fixedbitset/0.4.2 0.4.2 Apache-2.0 OR MIT + https://crates.io/crates/fnv/1.0.7 1.0.7 Apache-2.0 OR MIT + https://crates.io/crates/foreign-types/0.3.2 0.3.2 Apache-2.0 OR MIT + https://crates.io/crates/foreign-types-shared/0.1.1 0.1.1 Apache-2.0 OR MIT + https://crates.io/crates/form_urlencoded/1.1.0 1.1.0 Apache-2.0 OR MIT + https://crates.io/crates/futures-channel/0.3.25 0.3.25 Apache-2.0 OR MIT + https://crates.io/crates/futures-core/0.3.27 0.3.27 Apache-2.0 OR MIT + https://crates.io/crates/futures-io/0.3.27 0.3.27 Apache-2.0 OR MIT + https://crates.io/crates/futures-macro/0.3.27 0.3.27 Apache-2.0 OR MIT + https://crates.io/crates/futures-sink/0.3.27 0.3.27 Apache-2.0 OR MIT + https://crates.io/crates/futures-task/0.3.27 0.3.27 Apache-2.0 OR MIT + https://crates.io/crates/futures-util/0.3.27 0.3.27 Apache-2.0 OR MIT + https://crates.io/crates/getrandom/0.2.8 0.2.8 Apache-2.0 OR MIT + https://crates.io/crates/gimli/0.27.0 0.27.0 Apache-2.0 OR MIT + https://crates.io/crates/glob/0.3.1 0.3.1 Apache-2.0 OR MIT + https://crates.io/crates/hashbrown/0.12.3 0.12.3 Apache-2.0 OR MIT + https://crates.io/crates/heck/0.4.1 0.4.1 Apache-2.0 OR MIT + https://crates.io/crates/hermit-abi/0.2.6 0.2.6 Apache-2.0 OR MIT + https://crates.io/crates/http/0.2.9 0.2.9 Apache-2.0 OR MIT + https://crates.io/crates/httparse/1.8.0 1.8.0 Apache-2.0 OR MIT + https://crates.io/crates/httpdate/1.0.2 1.0.2 Apache-2.0 OR MIT + https://crates.io/crates/humansize/2.1.3 2.1.3 Apache-2.0 OR MIT + https://crates.io/crates/hyper-timeout/0.4.1 0.4.1 Apache-2.0 OR MIT + https://crates.io/crates/hyper-tls/0.5.0 0.5.0 Apache-2.0 OR MIT + https://crates.io/crates/iana-time-zone/0.1.53 0.1.53 Apache-2.0 OR MIT + https://crates.io/crates/iana-time-zone-haiku/0.1.1 0.1.1 Apache-2.0 OR MIT + https://crates.io/crates/idna/0.2.3 0.2.3 Apache-2.0 OR MIT + https://crates.io/crates/idna/0.3.0 0.3.0 Apache-2.0 OR MIT + https://crates.io/crates/indexmap/1.9.2 1.9.2 Apache-2.0 OR MIT + https://crates.io/crates/ipconfig/0.3.1 0.3.1 Apache-2.0 OR MIT + https://crates.io/crates/ipnet/2.7.1 2.7.1 Apache-2.0 OR MIT + https://crates.io/crates/itertools/0.10.5 0.10.5 Apache-2.0 OR MIT + https://crates.io/crates/itoa/1.0.5 1.0.5 Apache-2.0 OR MIT + https://crates.io/crates/js-sys/0.3.60 0.3.60 Apache-2.0 OR MIT + https://crates.io/crates/lazy_static/1.4.0 1.4.0 Apache-2.0 OR MIT + https://crates.io/crates/lazycell/1.3.0 1.3.0 Apache-2.0 OR MIT + https://crates.io/crates/libc/0.2.140 0.2.140 Apache-2.0 OR MIT + https://crates.io/crates/libm/0.2.6 0.2.6 Apache-2.0 OR MIT + https://crates.io/crates/link-cplusplus/1.0.8 1.0.8 Apache-2.0 OR MIT + https://crates.io/crates/linked-hash-map/0.5.6 0.5.6 Apache-2.0 OR MIT + https://crates.io/crates/lock_api/0.4.9 0.4.9 Apache-2.0 OR MIT + https://crates.io/crates/log/0.4.17 0.4.17 Apache-2.0 OR MIT + https://crates.io/crates/lru-cache/0.1.2 0.1.2 Apache-2.0 OR MIT + https://crates.io/crates/match_cfg/0.1.0 0.1.0 Apache-2.0 OR MIT + https://crates.io/crates/mime/0.3.16 0.3.16 Apache-2.0 OR MIT + https://crates.io/crates/minimal-lexical/0.2.1 0.2.1 Apache-2.0 OR MIT + https://crates.io/crates/multimap/0.8.3 0.8.3 Apache-2.0 OR MIT + https://crates.io/crates/native-tls/0.2.11 0.2.11 Apache-2.0 OR MIT + https://crates.io/crates/num-integer/0.1.45 0.1.45 Apache-2.0 OR MIT + https://crates.io/crates/num-traits/0.2.15 0.2.15 Apache-2.0 OR MIT + https://crates.io/crates/num_cpus/1.15.0 1.15.0 Apache-2.0 OR MIT + https://crates.io/crates/object/0.30.1 0.30.1 Apache-2.0 OR MIT + https://crates.io/crates/once_cell/1.17.1 1.17.1 Apache-2.0 OR MIT + https://crates.io/crates/openssl-macros/0.1.0 0.1.0 Apache-2.0 OR MIT + https://crates.io/crates/openssl-probe/0.1.5 0.1.5 Apache-2.0 OR MIT + https://crates.io/crates/os_str_bytes/6.4.1 6.4.1 Apache-2.0 OR MIT + https://crates.io/crates/parking_lot/0.12.1 0.12.1 Apache-2.0 OR MIT + https://crates.io/crates/parking_lot_core/0.9.5 0.9.5 Apache-2.0 OR MIT + https://crates.io/crates/peeking_take_while/0.1.2 0.1.2 Apache-2.0 OR MIT + https://crates.io/crates/percent-encoding/2.2.0 2.2.0 Apache-2.0 OR MIT + https://crates.io/crates/pest/2.5.6 2.5.6 Apache-2.0 OR MIT + https://crates.io/crates/pest_derive/2.5.6 2.5.6 Apache-2.0 OR MIT + https://crates.io/crates/pest_generator/2.5.6 2.5.6 Apache-2.0 OR MIT + https://crates.io/crates/pest_meta/2.5.6 2.5.6 Apache-2.0 OR MIT + https://crates.io/crates/petgraph/0.6.2 0.6.2 Apache-2.0 OR MIT + https://crates.io/crates/pin-project/1.0.12 1.0.12 Apache-2.0 OR MIT + https://crates.io/crates/pin-project-internal/1.0.12 1.0.12 Apache-2.0 OR MIT + https://crates.io/crates/pin-project-lite/0.2.9 0.2.9 Apache-2.0 OR MIT + https://crates.io/crates/pin-utils/0.1.0 0.1.0 Apache-2.0 OR MIT + https://crates.io/crates/pkg-config/0.3.26 0.3.26 Apache-2.0 OR MIT + https://crates.io/crates/portable-atomic/0.3.19 0.3.19 Apache-2.0 OR MIT + https://crates.io/crates/ppv-lite86/0.2.17 0.2.17 Apache-2.0 OR MIT + https://crates.io/crates/prettyplease/0.1.23 0.1.23 Apache-2.0 OR MIT + https://crates.io/crates/proc-macro-error/1.0.4 1.0.4 Apache-2.0 OR MIT + https://crates.io/crates/proc-macro-error-attr/1.0.4 1.0.4 Apache-2.0 OR MIT + https://crates.io/crates/proc-macro2/1.0.51 1.0.51 Apache-2.0 OR MIT + https://crates.io/crates/quick-error/1.2.3 1.2.3 Apache-2.0 OR MIT + https://crates.io/crates/quote/1.0.23 1.0.23 Apache-2.0 OR MIT + https://crates.io/crates/rand/0.8.5 0.8.5 Apache-2.0 OR MIT + https://crates.io/crates/rand_chacha/0.3.1 0.3.1 Apache-2.0 OR MIT + https://crates.io/crates/rand_core/0.6.4 0.6.4 Apache-2.0 OR MIT + https://crates.io/crates/regex/1.7.1 1.7.1 Apache-2.0 OR MIT + https://crates.io/crates/regex-syntax/0.6.28 0.6.28 Apache-2.0 OR MIT + https://crates.io/crates/reqwest/0.11.14 0.11.14 Apache-2.0 OR MIT + https://crates.io/crates/resolv-conf/0.7.0 0.7.0 Apache-2.0 OR MIT + https://crates.io/crates/rustc-demangle/0.1.21 0.1.21 Apache-2.0 OR MIT + https://crates.io/crates/rustc-hash/1.1.0 1.1.0 Apache-2.0 OR MIT + https://crates.io/crates/rustc_version/0.4.0 0.4.0 Apache-2.0 OR MIT + https://crates.io/crates/rustversion/1.0.11 1.0.11 Apache-2.0 OR MIT + https://crates.io/crates/scopeguard/1.1.0 1.1.0 Apache-2.0 OR MIT + https://crates.io/crates/scratch/1.0.3 1.0.3 Apache-2.0 OR MIT + https://crates.io/crates/security-framework/2.7.0 2.7.0 Apache-2.0 OR MIT + https://crates.io/crates/security-framework-sys/2.6.1 2.6.1 Apache-2.0 OR MIT + https://crates.io/crates/semver/1.0.16 1.0.16 Apache-2.0 OR MIT + https://crates.io/crates/serde/1.0.155 1.0.155 Apache-2.0 OR MIT + https://crates.io/crates/serde_derive/1.0.155 1.0.155 Apache-2.0 OR MIT + https://crates.io/crates/serde_json/1.0.94 1.0.94 Apache-2.0 OR MIT + https://crates.io/crates/serde_path_to_error/0.1.9 0.1.9 Apache-2.0 OR MIT + https://crates.io/crates/serde_urlencoded/0.7.1 0.7.1 Apache-2.0 OR MIT + https://crates.io/crates/sha2/0.10.6 0.10.6 Apache-2.0 OR MIT + https://crates.io/crates/shlex/1.1.0 1.1.0 Apache-2.0 OR MIT + https://crates.io/crates/signal-hook-registry/1.4.0 1.4.0 Apache-2.0 OR MIT + https://crates.io/crates/siphasher/0.3.10 0.3.10 Apache-2.0 OR MIT + https://crates.io/crates/slug/0.1.4 0.1.4 Apache-2.0 OR MIT + https://crates.io/crates/smallvec/1.10.0 1.10.0 Apache-2.0 OR MIT + https://crates.io/crates/socket2/0.4.7 0.4.7 Apache-2.0 OR MIT + https://crates.io/crates/syn/1.0.109 1.0.109 Apache-2.0 OR MIT + https://crates.io/crates/tempfile/3.4.0 3.4.0 Apache-2.0 OR MIT + https://crates.io/crates/thiserror/1.0.39 1.0.39 Apache-2.0 OR MIT + https://crates.io/crates/thiserror-impl/1.0.39 1.0.39 Apache-2.0 OR MIT + https://crates.io/crates/thread_local/1.1.4 1.1.4 Apache-2.0 OR MIT + https://crates.io/crates/time/0.1.45 0.1.45 Apache-2.0 OR MIT + https://crates.io/crates/time/0.3.17 0.3.17 Apache-2.0 OR MIT + https://crates.io/crates/time-core/0.1.0 0.1.0 Apache-2.0 OR MIT + https://crates.io/crates/tokio-io-timeout/1.2.0 1.2.0 Apache-2.0 OR MIT + https://crates.io/crates/tokio-rustls/0.23.4 0.23.4 Apache-2.0 OR MIT + https://crates.io/crates/trust-dns-proto/0.22.0 0.22.0 Apache-2.0 OR MIT + https://crates.io/crates/trust-dns-resolver/0.22.0 0.22.0 Apache-2.0 OR MIT + https://crates.io/crates/typenum/1.16.0 1.16.0 Apache-2.0 OR MIT + https://crates.io/crates/ucd-trie/0.1.5 0.1.5 Apache-2.0 OR MIT + https://crates.io/crates/uncased/0.9.7 0.9.7 Apache-2.0 OR MIT + https://crates.io/crates/unic-char-property/0.9.0 0.9.0 Apache-2.0 OR MIT + https://crates.io/crates/unic-char-range/0.9.0 0.9.0 Apache-2.0 OR MIT + https://crates.io/crates/unic-common/0.9.0 0.9.0 Apache-2.0 OR MIT + https://crates.io/crates/unic-segment/0.9.0 0.9.0 Apache-2.0 OR MIT + https://crates.io/crates/unic-ucd-segment/0.9.0 0.9.0 Apache-2.0 OR MIT + https://crates.io/crates/unic-ucd-version/0.9.0 0.9.0 Apache-2.0 OR MIT + https://crates.io/crates/unicode-bidi/0.3.8 0.3.8 Apache-2.0 OR MIT + https://crates.io/crates/unicode-normalization/0.1.22 0.1.22 Apache-2.0 OR MIT + https://crates.io/crates/unicode-width/0.1.10 0.1.10 Apache-2.0 OR MIT + https://crates.io/crates/url/2.3.1 2.3.1 Apache-2.0 OR MIT + https://crates.io/crates/uuid/1.2.2 1.2.2 Apache-2.0 OR MIT + https://crates.io/crates/vcpkg/0.2.15 0.2.15 Apache-2.0 OR MIT + https://crates.io/crates/version_check/0.9.4 0.9.4 Apache-2.0 OR MIT + https://crates.io/crates/wasm-bindgen/0.2.83 0.2.83 Apache-2.0 OR MIT + https://crates.io/crates/wasm-bindgen-backend/0.2.83 0.2.83 Apache-2.0 OR MIT + https://crates.io/crates/wasm-bindgen-futures/0.4.33 0.4.33 Apache-2.0 OR MIT + https://crates.io/crates/wasm-bindgen-macro/0.2.83 0.2.83 Apache-2.0 OR MIT + https://crates.io/crates/wasm-bindgen-macro-support/0.2.83 0.2.83 Apache-2.0 OR MIT + https://crates.io/crates/wasm-bindgen-shared/0.2.83 0.2.83 Apache-2.0 OR MIT + https://crates.io/crates/wasm-streams/0.2.3 0.2.3 Apache-2.0 OR MIT + https://crates.io/crates/web-sys/0.3.60 0.3.60 Apache-2.0 OR MIT + https://crates.io/crates/widestring/0.5.1 0.5.1 Apache-2.0 OR MIT + https://crates.io/crates/winapi/0.3.9 0.3.9 Apache-2.0 OR MIT + https://crates.io/crates/winapi-i686-pc-windows-gnu/0.4.0 0.4.0 Apache-2.0 OR MIT + https://crates.io/crates/winapi-x86_64-pc-windows-gnu/0.4.0 0.4.0 Apache-2.0 OR MIT + https://crates.io/crates/windows-sys/0.42.0 0.42.0 Apache-2.0 OR MIT + https://crates.io/crates/windows-sys/0.45.0 0.45.0 Apache-2.0 OR MIT + https://crates.io/crates/windows-targets/0.42.1 0.42.1 Apache-2.0 OR MIT + https://crates.io/crates/windows_aarch64_gnullvm/0.42.1 0.42.1 Apache-2.0 OR MIT + https://crates.io/crates/windows_aarch64_msvc/0.42.1 0.42.1 Apache-2.0 OR MIT + https://crates.io/crates/windows_i686_gnu/0.42.1 0.42.1 Apache-2.0 OR MIT + https://crates.io/crates/windows_i686_msvc/0.42.1 0.42.1 Apache-2.0 OR MIT + https://crates.io/crates/windows_x86_64_gnu/0.42.1 0.42.1 Apache-2.0 OR MIT + https://crates.io/crates/windows_x86_64_gnullvm/0.42.1 0.42.1 Apache-2.0 OR MIT + https://crates.io/crates/windows_x86_64_msvc/0.42.1 0.42.1 Apache-2.0 OR MIT + +======================================================================== +Apache-2.0 OR MIT OR Zlib licenses +======================================================================== +The following components are provided under the Apache-2.0 OR MIT OR Zlib License. See project link for details. +The text of each license is also included in licenses/LICENSE-[project].txt. + + https://crates.io/crates/miniz_oxide/0.6.2 0.6.2 Apache-2.0 OR MIT OR Zlib + https://crates.io/crates/tinyvec/1.6.0 1.6.0 Apache-2.0 OR MIT OR Zlib + https://crates.io/crates/tinyvec_macros/0.1.0 0.1.0 Apache-2.0 OR MIT OR Zlib + +======================================================================== +BSD-3-Clause licenses +======================================================================== +The following components are provided under the BSD-3-Clause License. See project link for details. +The text of each license is also included in licenses/LICENSE-[project].txt. + + https://crates.io/crates/bindgen/0.63.0 0.63.0 BSD-3-Clause + https://crates.io/crates/deunicode/0.4.3 0.4.3 BSD-3-Clause + https://crates.io/crates/instant/0.1.12 0.1.12 BSD-3-Clause + +======================================================================== +ISC licenses +======================================================================== +The following components are provided under the ISC License. See project link for details. +The text of each license is also included in licenses/LICENSE-[project].txt. + + https://crates.io/crates/libloading/0.7.4 0.7.4 ISC + https://crates.io/crates/untrusted/0.7.1 0.7.1 ISC + https://crates.io/crates/webpki/0.22.0 0.22.0 ISC + +======================================================================== +ISC and OpenSSL and MIT licenses +======================================================================== +The following components are provided under the ISC and OpenSSL and MIT License. See project link for details. +The text of each license is also included in licenses/LICENSE-[project].txt. + + https://crates.io/crates/ring/0.16.20 0.16.20 ISC and OpenSSL and MIT + +======================================================================== +MIT licenses +======================================================================== +The following components are provided under the MIT License. See project link for details. +The text of each license is also included in licenses/LICENSE-[project].txt. + + https://crates.io/crates/async-stream/0.3.3 0.3.3 MIT + https://crates.io/crates/async-stream-impl/0.3.3 0.3.3 MIT + https://crates.io/crates/axum/0.6.11 0.6.11 MIT + https://crates.io/crates/axum-core/0.3.3 0.3.3 MIT + https://crates.io/crates/bincode/1.3.3 1.3.3 MIT + https://crates.io/crates/bytes/1.3.0 1.3.0 MIT + https://crates.io/crates/convert_case/0.4.0 0.4.0 MIT + https://crates.io/crates/dashmap/5.4.0 5.4.0 MIT + https://crates.io/crates/data-encoding/2.3.3 2.3.3 MIT + https://crates.io/crates/derive_more/0.99.17 0.99.17 MIT + https://crates.io/crates/errno-dragonfly/0.1.2 0.1.2 MIT + https://crates.io/crates/generic-array/0.14.6 0.14.6 MIT + https://crates.io/crates/globwalk/0.8.1 0.8.1 MIT + https://crates.io/crates/h2/0.3.17 0.3.17 MIT + https://crates.io/crates/hostname/0.3.1 0.3.1 MIT + https://crates.io/crates/http-body/0.4.5 0.4.5 MIT + https://crates.io/crates/hyper/0.14.25 0.14.25 MIT + https://crates.io/crates/is-terminal/0.4.2 0.4.2 MIT + https://crates.io/crates/matches/0.1.9 0.1.9 MIT + https://crates.io/crates/matchit/0.7.0 0.7.0 MIT + https://crates.io/crates/mio/0.8.5 0.8.5 MIT + https://crates.io/crates/nom/7.1.2 7.1.2 MIT + https://crates.io/crates/nu-ansi-term/0.46.0 0.46.0 MIT + https://crates.io/crates/openssl-sys/0.9.83 0.9.83 MIT + https://crates.io/crates/overload/0.1.1 0.1.1 MIT + https://crates.io/crates/parse-zoneinfo/0.3.0 0.3.0 MIT + https://crates.io/crates/phf/0.10.1 0.10.1 MIT + https://crates.io/crates/phf_codegen/0.10.0 0.10.0 MIT + https://crates.io/crates/phf_generator/0.10.0 0.10.0 MIT + https://crates.io/crates/phf_shared/0.10.0 0.10.0 MIT + https://crates.io/crates/redox_syscall/0.2.16 0.2.16 MIT + https://crates.io/crates/schannel/0.1.21 0.1.21 MIT + https://crates.io/crates/sharded-slab/0.1.4 0.1.4 MIT + https://crates.io/crates/slab/0.4.7 0.4.7 MIT + https://crates.io/crates/spin/0.5.2 0.5.2 MIT + https://crates.io/crates/strsim/0.10.0 0.10.0 MIT + https://crates.io/crates/tera/1.18.0 1.18.0 MIT + https://crates.io/crates/tokio/1.26.0 1.26.0 MIT + https://crates.io/crates/tokio-macros/1.8.2 1.8.2 MIT + https://crates.io/crates/tokio-native-tls/0.3.0 0.3.0 MIT + https://crates.io/crates/tokio-stream/0.1.12 0.1.12 MIT + https://crates.io/crates/tokio-util/0.7.4 0.7.4 MIT + https://crates.io/crates/tonic/0.8.3 0.8.3 MIT + https://crates.io/crates/tonic-build/0.8.4 0.8.4 MIT + https://crates.io/crates/tower/0.4.13 0.4.13 MIT + https://crates.io/crates/tower-layer/0.3.2 0.3.2 MIT + https://crates.io/crates/tower-service/0.3.2 0.3.2 MIT + https://crates.io/crates/tracing/0.1.37 0.1.37 MIT + https://crates.io/crates/tracing-attributes/0.1.23 0.1.23 MIT + https://crates.io/crates/tracing-core/0.1.30 0.1.30 MIT + https://crates.io/crates/tracing-futures/0.2.5 0.2.5 MIT + https://crates.io/crates/tracing-log/0.1.3 0.1.3 MIT + https://crates.io/crates/tracing-subscriber/0.3.16 0.3.16 MIT + https://crates.io/crates/try-lock/0.2.4 0.2.4 MIT + https://crates.io/crates/valuable/0.1.0 0.1.0 MIT + https://crates.io/crates/want/0.3.0 0.3.0 MIT + https://crates.io/crates/which/4.4.0 4.4.0 MIT + https://crates.io/crates/winreg/0.10.1 0.10.1 MIT + +======================================================================== +MIT OR Unlicense licenses +======================================================================== +The following components are provided under the MIT OR Unlicense License. See project link for details. +The text of each license is also included in licenses/LICENSE-[project].txt. + + https://crates.io/crates/aho-corasick/0.7.20 0.7.20 MIT OR Unlicense + https://crates.io/crates/globset/0.4.10 0.4.10 MIT OR Unlicense + https://crates.io/crates/ignore/0.4.19 0.4.19 MIT OR Unlicense + https://crates.io/crates/memchr/2.5.0 2.5.0 MIT OR Unlicense + https://crates.io/crates/same-file/1.0.6 1.0.6 MIT OR Unlicense + https://crates.io/crates/termcolor/1.2.0 1.2.0 MIT OR Unlicense + https://crates.io/crates/walkdir/2.3.2 2.3.2 MIT OR Unlicense + https://crates.io/crates/winapi-util/0.1.5 0.1.5 MIT OR Unlicense + +======================================================================== +MulanPSL-2.0 licenses +======================================================================== +The following components are provided under the MulanPSL-2.0 License. See project link for details. +The text of each license is also included in licenses/LICENSE-[project].txt. + + https://crates.io/crates/phper/0.11.1 0.11.1 MulanPSL-2.0 + https://crates.io/crates/phper-alloc/0.11.1 0.11.1 MulanPSL-2.0 + https://crates.io/crates/phper-build/0.11.1 0.11.1 MulanPSL-2.0 + https://crates.io/crates/phper-macros/0.11.1 0.11.1 MulanPSL-2.0 + https://crates.io/crates/phper-sys/0.11.1 0.11.1 MulanPSL-2.0 + +======================================================================== +Unlicense licenses +======================================================================== +The following components are provided under the Unlicense License. See project link for details. +The text of each license is also included in licenses/LICENSE-[project].txt. + + https://crates.io/crates/systemstat/0.2.3 0.2.3 Unlicense + diff --git a/dist-material/LICENSE.tpl b/dist-material/LICENSE.tpl new file mode 100644 index 0000000..cb845a3 --- /dev/null +++ b/dist-material/LICENSE.tpl @@ -0,0 +1,26 @@ +{{ .LicenseContent }} + +======================================================================= +Apache SkyWalking Subcomponents: + +The Apache SkyWalking project contains subcomponents with separate copyright +notices and license terms. Your use of the source code for the these +subcomponents is subject to the terms and conditions of the following +licenses. +======================================================================== + +{{ range .Groups }} +======================================================================== +{{ .LicenseID }} licenses +======================================================================== +The following components are provided under the {{ .LicenseID }} License. See project link for details. +{{- if contains .LicenseID "Apache-2.0" }} +The text of each license is the standard Apache 2.0 license. +{{- else }} +The text of each license is also included in licenses/LICENSE-[project].txt. +{{ end }} + + {{- range .Deps }} + https://crates.io/crates/{{ .Name }}/{{ .Version }} {{ .Version }} {{ .LicenseID }} + {{- end }} +{{ end }} diff --git a/dist-material/NOTICE b/dist-material/NOTICE new file mode 100644 index 0000000..9444a36 --- /dev/null +++ b/dist-material/NOTICE @@ -0,0 +1,6 @@ +Apache SkyWalking +Copyright 2017-2023 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + diff --git a/dist-material/licenses/LICENSE-aho-corasick.txt b/dist-material/licenses/LICENSE-aho-corasick.txt new file mode 100644 index 0000000..3b0a5dc --- /dev/null +++ b/dist-material/licenses/LICENSE-aho-corasick.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Andrew Gallant + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-async-stream-impl.txt b/dist-material/licenses/LICENSE-async-stream-impl.txt new file mode 100644 index 0000000..8cbd7d6 --- /dev/null +++ b/dist-material/licenses/LICENSE-async-stream-impl.txt @@ -0,0 +1,51 @@ +Copyright (c) 2019 Carl Lerche + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +Copyright (c) 2018 David Tolnay + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-async-stream.txt b/dist-material/licenses/LICENSE-async-stream.txt new file mode 100644 index 0000000..8cbd7d6 --- /dev/null +++ b/dist-material/licenses/LICENSE-async-stream.txt @@ -0,0 +1,51 @@ +Copyright (c) 2019 Carl Lerche + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +Copyright (c) 2018 David Tolnay + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-axum-core.txt b/dist-material/licenses/LICENSE-axum-core.txt new file mode 100644 index 0000000..538d04a --- /dev/null +++ b/dist-material/licenses/LICENSE-axum-core.txt @@ -0,0 +1,7 @@ +Copyright 2021 Axum Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-axum.txt b/dist-material/licenses/LICENSE-axum.txt new file mode 100644 index 0000000..11598b4 --- /dev/null +++ b/dist-material/licenses/LICENSE-axum.txt @@ -0,0 +1,25 @@ +Copyright (c) 2019 Axum Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-bincode.txt b/dist-material/licenses/LICENSE-bincode.txt new file mode 100644 index 0000000..3db1f01 --- /dev/null +++ b/dist-material/licenses/LICENSE-bincode.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Ty Overby + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dist-material/licenses/LICENSE-bindgen.txt b/dist-material/licenses/LICENSE-bindgen.txt new file mode 100644 index 0000000..62f55f4 --- /dev/null +++ b/dist-material/licenses/LICENSE-bindgen.txt @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2013, Jyun-Yan You +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/dist-material/licenses/LICENSE-bytes.txt b/dist-material/licenses/LICENSE-bytes.txt new file mode 100644 index 0000000..58fb29a --- /dev/null +++ b/dist-material/licenses/LICENSE-bytes.txt @@ -0,0 +1,25 @@ +Copyright (c) 2018 Carl Lerche + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-convert_case.txt b/dist-material/licenses/LICENSE-convert_case.txt new file mode 100644 index 0000000..aea2ac6 --- /dev/null +++ b/dist-material/licenses/LICENSE-convert_case.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 David Purdum + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dist-material/licenses/LICENSE-dashmap.txt b/dist-material/licenses/LICENSE-dashmap.txt new file mode 100644 index 0000000..5a8b9ef --- /dev/null +++ b/dist-material/licenses/LICENSE-dashmap.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Acrimon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dist-material/licenses/LICENSE-data-encoding.txt b/dist-material/licenses/LICENSE-data-encoding.txt new file mode 100644 index 0000000..9a75083 --- /dev/null +++ b/dist-material/licenses/LICENSE-data-encoding.txt @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015-2020 Julien Cretin +Copyright (c) 2017-2020 Google Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dist-material/licenses/LICENSE-derive_more.txt b/dist-material/licenses/LICENSE-derive_more.txt new file mode 100644 index 0000000..602cf05 --- /dev/null +++ b/dist-material/licenses/LICENSE-derive_more.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Jelte Fennema + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dist-material/licenses/LICENSE-errno-dragonfly.txt b/dist-material/licenses/LICENSE-errno-dragonfly.txt new file mode 100644 index 0000000..1f1500c --- /dev/null +++ b/dist-material/licenses/LICENSE-errno-dragonfly.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Michael Neumann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dist-material/licenses/LICENSE-h2.txt b/dist-material/licenses/LICENSE-h2.txt new file mode 100644 index 0000000..11239dd --- /dev/null +++ b/dist-material/licenses/LICENSE-h2.txt @@ -0,0 +1,25 @@ +Copyright (c) 2017 h2 authors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-hostname.txt b/dist-material/licenses/LICENSE-hostname.txt new file mode 100644 index 0000000..0a564fa --- /dev/null +++ b/dist-material/licenses/LICENSE-hostname.txt @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2016 fengcen +Copyright (c) 2019 svartalf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dist-material/licenses/LICENSE-http-body.txt b/dist-material/licenses/LICENSE-http-body.txt new file mode 100644 index 0000000..27b08f2 --- /dev/null +++ b/dist-material/licenses/LICENSE-http-body.txt @@ -0,0 +1,25 @@ +Copyright (c) 2019 Hyper Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-hyper.txt b/dist-material/licenses/LICENSE-hyper.txt new file mode 100644 index 0000000..bc1e966 --- /dev/null +++ b/dist-material/licenses/LICENSE-hyper.txt @@ -0,0 +1,19 @@ +Copyright (c) 2014-2021 Sean McArthur + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-instant.txt b/dist-material/licenses/LICENSE-instant.txt new file mode 100644 index 0000000..f8062f3 --- /dev/null +++ b/dist-material/licenses/LICENSE-instant.txt @@ -0,0 +1,27 @@ +Copyright (c) 2019, Sébastien Crozet +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/dist-material/licenses/LICENSE-libloading.txt b/dist-material/licenses/LICENSE-libloading.txt new file mode 100644 index 0000000..9137d56 --- /dev/null +++ b/dist-material/licenses/LICENSE-libloading.txt @@ -0,0 +1,12 @@ +Copyright © 2015, Simonas Kazlauskas + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without +fee is hereby granted, provided that the above copyright notice and this permission notice appear +in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/dist-material/licenses/LICENSE-matches.txt b/dist-material/licenses/LICENSE-matches.txt new file mode 100644 index 0000000..a7b759a --- /dev/null +++ b/dist-material/licenses/LICENSE-matches.txt @@ -0,0 +1,25 @@ +Copyright (c) 2014-2016 Simon Sapin + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-matchit.txt b/dist-material/licenses/LICENSE-matchit.txt new file mode 100644 index 0000000..24411c7 --- /dev/null +++ b/dist-material/licenses/LICENSE-matchit.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Ibraheem Ahmed + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dist-material/licenses/LICENSE-memchr.txt b/dist-material/licenses/LICENSE-memchr.txt new file mode 100644 index 0000000..3b0a5dc --- /dev/null +++ b/dist-material/licenses/LICENSE-memchr.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Andrew Gallant + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-mio.txt b/dist-material/licenses/LICENSE-mio.txt new file mode 100644 index 0000000..3516413 --- /dev/null +++ b/dist-material/licenses/LICENSE-mio.txt @@ -0,0 +1,19 @@ +Copyright (c) 2014 Carl Lerche and other MIO contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-nom.txt b/dist-material/licenses/LICENSE-nom.txt new file mode 100644 index 0000000..88557e4 --- /dev/null +++ b/dist-material/licenses/LICENSE-nom.txt @@ -0,0 +1,20 @@ +Copyright (c) 2014-2019 Geoffroy Couprie + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-nu-ansi-term.txt b/dist-material/licenses/LICENSE-nu-ansi-term.txt new file mode 100644 index 0000000..f392dfc --- /dev/null +++ b/dist-material/licenses/LICENSE-nu-ansi-term.txt @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2014 Benjamin Sago +Copyright (c) 2021-2022 The Nushell Project Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dist-material/licenses/LICENSE-openssl-sys.txt b/dist-material/licenses/LICENSE-openssl-sys.txt new file mode 100644 index 0000000..39e0ed6 --- /dev/null +++ b/dist-material/licenses/LICENSE-openssl-sys.txt @@ -0,0 +1,25 @@ +Copyright (c) 2014 Alex Crichton + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-overload.txt b/dist-material/licenses/LICENSE-overload.txt new file mode 100644 index 0000000..0ed504b --- /dev/null +++ b/dist-material/licenses/LICENSE-overload.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Daniel Augusto Rizzi Salvadori + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/dist-material/licenses/LICENSE-phper-alloc.txt b/dist-material/licenses/LICENSE-phper-alloc.txt new file mode 100644 index 0000000..9e32cde --- /dev/null +++ b/dist-material/licenses/LICENSE-phper-alloc.txt @@ -0,0 +1,127 @@ + 木兰宽松许可证, 第2版 + + 木兰宽松许可证, 第2版 + 2020年1月 http://license.coscl.org.cn/MulanPSL2 + + + 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束: + + 0. 定义 + + “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 + + “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 + + “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 + + “法人实体”是指提交贡献的机构及其“关联实体”。 + + “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 + + 1. 授予版权许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 + + 2. 授予专利许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 + + 3. 无商标许可 + + “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 + + 4. 分发限制 + + 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 + + 5. 免责声明与责任限制 + + “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 + + 6. 语言 + “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。 + + 条款结束 + + 如何将木兰宽松许可证,第2版,应用到您的软件 + + 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: + + 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; + + 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; + + 3, 请将如下声明文本放入每个源文件的头部注释中。 + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. + + + Mulan Permissive Software License,Version 2 + + Mulan Permissive Software License,Version 2 (Mulan PSL v2) + January 2020 http://license.coscl.org.cn/MulanPSL2 + + Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions: + + 0. Definition + + Software means the program and related documents which are licensed under this License and comprise all Contribution(s). + + Contribution means the copyrightable work licensed by a particular Contributor under this License. + + Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. + + Legal Entity means the entity making a Contribution and all its Affiliates. + + Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. + + 1. Grant of Copyright License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. + + 2. Grant of Patent License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. + + 3. No Trademark License + + No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4. + + 4. Distribution Restriction + + You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. + + 5. Disclaimer of Warranty and Limitation of Liability + + THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + 6. Language + + THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL. + + END OF THE TERMS AND CONDITIONS + + How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software + + To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps: + + i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; + + ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package; + + iii Attach the statement to the appropriate annotated syntax at the beginning of each source file. + + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. diff --git a/dist-material/licenses/LICENSE-phper-build.txt b/dist-material/licenses/LICENSE-phper-build.txt new file mode 100644 index 0000000..9e32cde --- /dev/null +++ b/dist-material/licenses/LICENSE-phper-build.txt @@ -0,0 +1,127 @@ + 木兰宽松许可证, 第2版 + + 木兰宽松许可证, 第2版 + 2020年1月 http://license.coscl.org.cn/MulanPSL2 + + + 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束: + + 0. 定义 + + “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 + + “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 + + “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 + + “法人实体”是指提交贡献的机构及其“关联实体”。 + + “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 + + 1. 授予版权许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 + + 2. 授予专利许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 + + 3. 无商标许可 + + “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 + + 4. 分发限制 + + 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 + + 5. 免责声明与责任限制 + + “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 + + 6. 语言 + “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。 + + 条款结束 + + 如何将木兰宽松许可证,第2版,应用到您的软件 + + 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: + + 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; + + 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; + + 3, 请将如下声明文本放入每个源文件的头部注释中。 + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. + + + Mulan Permissive Software License,Version 2 + + Mulan Permissive Software License,Version 2 (Mulan PSL v2) + January 2020 http://license.coscl.org.cn/MulanPSL2 + + Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions: + + 0. Definition + + Software means the program and related documents which are licensed under this License and comprise all Contribution(s). + + Contribution means the copyrightable work licensed by a particular Contributor under this License. + + Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. + + Legal Entity means the entity making a Contribution and all its Affiliates. + + Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. + + 1. Grant of Copyright License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. + + 2. Grant of Patent License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. + + 3. No Trademark License + + No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4. + + 4. Distribution Restriction + + You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. + + 5. Disclaimer of Warranty and Limitation of Liability + + THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + 6. Language + + THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL. + + END OF THE TERMS AND CONDITIONS + + How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software + + To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps: + + i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; + + ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package; + + iii Attach the statement to the appropriate annotated syntax at the beginning of each source file. + + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. diff --git a/dist-material/licenses/LICENSE-phper-macros.txt b/dist-material/licenses/LICENSE-phper-macros.txt new file mode 100644 index 0000000..9e32cde --- /dev/null +++ b/dist-material/licenses/LICENSE-phper-macros.txt @@ -0,0 +1,127 @@ + 木兰宽松许可证, 第2版 + + 木兰宽松许可证, 第2版 + 2020年1月 http://license.coscl.org.cn/MulanPSL2 + + + 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束: + + 0. 定义 + + “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 + + “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 + + “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 + + “法人实体”是指提交贡献的机构及其“关联实体”。 + + “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 + + 1. 授予版权许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 + + 2. 授予专利许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 + + 3. 无商标许可 + + “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 + + 4. 分发限制 + + 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 + + 5. 免责声明与责任限制 + + “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 + + 6. 语言 + “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。 + + 条款结束 + + 如何将木兰宽松许可证,第2版,应用到您的软件 + + 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: + + 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; + + 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; + + 3, 请将如下声明文本放入每个源文件的头部注释中。 + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. + + + Mulan Permissive Software License,Version 2 + + Mulan Permissive Software License,Version 2 (Mulan PSL v2) + January 2020 http://license.coscl.org.cn/MulanPSL2 + + Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions: + + 0. Definition + + Software means the program and related documents which are licensed under this License and comprise all Contribution(s). + + Contribution means the copyrightable work licensed by a particular Contributor under this License. + + Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. + + Legal Entity means the entity making a Contribution and all its Affiliates. + + Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. + + 1. Grant of Copyright License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. + + 2. Grant of Patent License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. + + 3. No Trademark License + + No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4. + + 4. Distribution Restriction + + You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. + + 5. Disclaimer of Warranty and Limitation of Liability + + THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + 6. Language + + THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL. + + END OF THE TERMS AND CONDITIONS + + How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software + + To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps: + + i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; + + ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package; + + iii Attach the statement to the appropriate annotated syntax at the beginning of each source file. + + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. diff --git a/dist-material/licenses/LICENSE-phper-sys.txt b/dist-material/licenses/LICENSE-phper-sys.txt new file mode 100644 index 0000000..9e32cde --- /dev/null +++ b/dist-material/licenses/LICENSE-phper-sys.txt @@ -0,0 +1,127 @@ + 木兰宽松许可证, 第2版 + + 木兰宽松许可证, 第2版 + 2020年1月 http://license.coscl.org.cn/MulanPSL2 + + + 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束: + + 0. 定义 + + “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 + + “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 + + “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 + + “法人实体”是指提交贡献的机构及其“关联实体”。 + + “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 + + 1. 授予版权许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 + + 2. 授予专利许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 + + 3. 无商标许可 + + “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 + + 4. 分发限制 + + 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 + + 5. 免责声明与责任限制 + + “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 + + 6. 语言 + “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。 + + 条款结束 + + 如何将木兰宽松许可证,第2版,应用到您的软件 + + 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: + + 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; + + 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; + + 3, 请将如下声明文本放入每个源文件的头部注释中。 + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. + + + Mulan Permissive Software License,Version 2 + + Mulan Permissive Software License,Version 2 (Mulan PSL v2) + January 2020 http://license.coscl.org.cn/MulanPSL2 + + Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions: + + 0. Definition + + Software means the program and related documents which are licensed under this License and comprise all Contribution(s). + + Contribution means the copyrightable work licensed by a particular Contributor under this License. + + Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. + + Legal Entity means the entity making a Contribution and all its Affiliates. + + Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. + + 1. Grant of Copyright License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. + + 2. Grant of Patent License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. + + 3. No Trademark License + + No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4. + + 4. Distribution Restriction + + You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. + + 5. Disclaimer of Warranty and Limitation of Liability + + THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + 6. Language + + THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL. + + END OF THE TERMS AND CONDITIONS + + How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software + + To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps: + + i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; + + ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package; + + iii Attach the statement to the appropriate annotated syntax at the beginning of each source file. + + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. diff --git a/dist-material/licenses/LICENSE-phper.txt b/dist-material/licenses/LICENSE-phper.txt new file mode 100644 index 0000000..9e32cde --- /dev/null +++ b/dist-material/licenses/LICENSE-phper.txt @@ -0,0 +1,127 @@ + 木兰宽松许可证, 第2版 + + 木兰宽松许可证, 第2版 + 2020年1月 http://license.coscl.org.cn/MulanPSL2 + + + 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束: + + 0. 定义 + + “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 + + “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 + + “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 + + “法人实体”是指提交贡献的机构及其“关联实体”。 + + “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 + + 1. 授予版权许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 + + 2. 授予专利许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 + + 3. 无商标许可 + + “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 + + 4. 分发限制 + + 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 + + 5. 免责声明与责任限制 + + “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 + + 6. 语言 + “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。 + + 条款结束 + + 如何将木兰宽松许可证,第2版,应用到您的软件 + + 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: + + 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; + + 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; + + 3, 请将如下声明文本放入每个源文件的头部注释中。 + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. + + + Mulan Permissive Software License,Version 2 + + Mulan Permissive Software License,Version 2 (Mulan PSL v2) + January 2020 http://license.coscl.org.cn/MulanPSL2 + + Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions: + + 0. Definition + + Software means the program and related documents which are licensed under this License and comprise all Contribution(s). + + Contribution means the copyrightable work licensed by a particular Contributor under this License. + + Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. + + Legal Entity means the entity making a Contribution and all its Affiliates. + + Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. + + 1. Grant of Copyright License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. + + 2. Grant of Patent License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. + + 3. No Trademark License + + No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4. + + 4. Distribution Restriction + + You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. + + 5. Disclaimer of Warranty and Limitation of Liability + + THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + 6. Language + + THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL. + + END OF THE TERMS AND CONDITIONS + + How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software + + To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps: + + i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; + + ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package; + + iii Attach the statement to the appropriate annotated syntax at the beginning of each source file. + + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. diff --git a/dist-material/licenses/LICENSE-redox_syscall.txt b/dist-material/licenses/LICENSE-redox_syscall.txt new file mode 100644 index 0000000..1292bb7 --- /dev/null +++ b/dist-material/licenses/LICENSE-redox_syscall.txt @@ -0,0 +1,22 @@ +Copyright (c) 2017 Redox OS Developers + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-ring.txt b/dist-material/licenses/LICENSE-ring.txt new file mode 100644 index 0000000..bf78743 --- /dev/null +++ b/dist-material/licenses/LICENSE-ring.txt @@ -0,0 +1,204 @@ +Note that it is easy for this file to get out of sync with the licenses in the +source code files. It's recommended to compare the licenses in the source code +with what's mentioned here. + +*ring* is derived from BoringSSL, so the licensing situation in *ring* is +similar to BoringSSL. + +*ring* uses an ISC-style license like BoringSSL for code in new files, +including in particular all the Rust code: + + Copyright 2015-2016 Brian Smith. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL +licensing. Files that are completely new have a Google copyright and an ISC +license. This license is reproduced at the bottom of this file. + +Contributors to BoringSSL are required to follow the CLA rules for Chromium: +https://cla.developers.google.com/clas + +Files in third_party/ have their own licenses, as described therein. The MIT +license, for third_party/fiat, which, unlike other third_party directories, is +compiled into non-test libraries, is included below. + +The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the +OpenSSL License and the original SSLeay license apply to the toolkit. See below +for the actual license texts. Actually both licenses are BSD-style Open Source +licenses. In case of any license issues related to OpenSSL please contact +openssl-core@openssl.org. + +The following are Google-internal bug numbers where explicit permission from +some authors is recorded for use of their work: + 27287199 + 27287880 + 27287883 + + OpenSSL License + --------------- + +/* ==================================================================== + * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + Original SSLeay License + ----------------------- + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + + +ISC license used for completely new code in BoringSSL: + +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + + +The code in third_party/fiat carries the MIT license: + +Copyright (c) 2015-2016 the fiat-crypto authors (see +https://github.com/mit-plv/fiat-crypto/blob/master/AUTHORS). + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dist-material/licenses/LICENSE-schannel.txt b/dist-material/licenses/LICENSE-schannel.txt new file mode 100644 index 0000000..0d9d26d --- /dev/null +++ b/dist-material/licenses/LICENSE-schannel.txt @@ -0,0 +1,7 @@ +Copyright (c) 2015 steffengy + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-sharded-slab.txt b/dist-material/licenses/LICENSE-sharded-slab.txt new file mode 100644 index 0000000..254e856 --- /dev/null +++ b/dist-material/licenses/LICENSE-sharded-slab.txt @@ -0,0 +1,19 @@ +Copyright (c) 2019 Eliza Weisman + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-slab.txt b/dist-material/licenses/LICENSE-slab.txt new file mode 100644 index 0000000..819ce21 --- /dev/null +++ b/dist-material/licenses/LICENSE-slab.txt @@ -0,0 +1,25 @@ +Copyright (c) 2019 Carl Lerche + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-spin.txt b/dist-material/licenses/LICENSE-spin.txt new file mode 100644 index 0000000..b2d7f7b --- /dev/null +++ b/dist-material/licenses/LICENSE-spin.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Mathijs van de Nes + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/dist-material/licenses/LICENSE-systemstat.txt b/dist-material/licenses/LICENSE-systemstat.txt new file mode 100644 index 0000000..68a49da --- /dev/null +++ b/dist-material/licenses/LICENSE-systemstat.txt @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/dist-material/licenses/LICENSE-termcolor.txt b/dist-material/licenses/LICENSE-termcolor.txt new file mode 100644 index 0000000..3b0a5dc --- /dev/null +++ b/dist-material/licenses/LICENSE-termcolor.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Andrew Gallant + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-tokio-macros.txt b/dist-material/licenses/LICENSE-tokio-macros.txt new file mode 100644 index 0000000..a3753c0 --- /dev/null +++ b/dist-material/licenses/LICENSE-tokio-macros.txt @@ -0,0 +1,47 @@ +Copyright (c) 2022 Tokio Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +The MIT License (MIT) + +Copyright (c) 2019 Yoshua Wuyts + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dist-material/licenses/LICENSE-tokio-native-tls.txt b/dist-material/licenses/LICENSE-tokio-native-tls.txt new file mode 100644 index 0000000..cdb28b4 --- /dev/null +++ b/dist-material/licenses/LICENSE-tokio-native-tls.txt @@ -0,0 +1,25 @@ +Copyright (c) 2019 Tokio Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-tokio-stream.txt b/dist-material/licenses/LICENSE-tokio-stream.txt new file mode 100644 index 0000000..8bdf6bd --- /dev/null +++ b/dist-material/licenses/LICENSE-tokio-stream.txt @@ -0,0 +1,25 @@ +Copyright (c) 2023 Tokio Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-tokio-util.txt b/dist-material/licenses/LICENSE-tokio-util.txt new file mode 100644 index 0000000..8af5baf --- /dev/null +++ b/dist-material/licenses/LICENSE-tokio-util.txt @@ -0,0 +1,25 @@ +Copyright (c) 2022 Tokio Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-tokio.txt b/dist-material/licenses/LICENSE-tokio.txt new file mode 100644 index 0000000..8bdf6bd --- /dev/null +++ b/dist-material/licenses/LICENSE-tokio.txt @@ -0,0 +1,25 @@ +Copyright (c) 2023 Tokio Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-tonic-build.txt b/dist-material/licenses/LICENSE-tonic-build.txt new file mode 100644 index 0000000..3077098 --- /dev/null +++ b/dist-material/licenses/LICENSE-tonic-build.txt @@ -0,0 +1,19 @@ +Copyright (c) 2020 Lucio Franco + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-tonic.txt b/dist-material/licenses/LICENSE-tonic.txt new file mode 100644 index 0000000..3077098 --- /dev/null +++ b/dist-material/licenses/LICENSE-tonic.txt @@ -0,0 +1,19 @@ +Copyright (c) 2020 Lucio Franco + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-tower-layer.txt b/dist-material/licenses/LICENSE-tower-layer.txt new file mode 100644 index 0000000..b980cac --- /dev/null +++ b/dist-material/licenses/LICENSE-tower-layer.txt @@ -0,0 +1,25 @@ +Copyright (c) 2019 Tower Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-tower-service.txt b/dist-material/licenses/LICENSE-tower-service.txt new file mode 100644 index 0000000..b980cac --- /dev/null +++ b/dist-material/licenses/LICENSE-tower-service.txt @@ -0,0 +1,25 @@ +Copyright (c) 2019 Tower Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-tower.txt b/dist-material/licenses/LICENSE-tower.txt new file mode 100644 index 0000000..b980cac --- /dev/null +++ b/dist-material/licenses/LICENSE-tower.txt @@ -0,0 +1,25 @@ +Copyright (c) 2019 Tower Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-tracing-attributes.txt b/dist-material/licenses/LICENSE-tracing-attributes.txt new file mode 100644 index 0000000..cdb28b4 --- /dev/null +++ b/dist-material/licenses/LICENSE-tracing-attributes.txt @@ -0,0 +1,25 @@ +Copyright (c) 2019 Tokio Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-tracing-core.txt b/dist-material/licenses/LICENSE-tracing-core.txt new file mode 100644 index 0000000..cdb28b4 --- /dev/null +++ b/dist-material/licenses/LICENSE-tracing-core.txt @@ -0,0 +1,25 @@ +Copyright (c) 2019 Tokio Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-tracing-futures.txt b/dist-material/licenses/LICENSE-tracing-futures.txt new file mode 100644 index 0000000..cdb28b4 --- /dev/null +++ b/dist-material/licenses/LICENSE-tracing-futures.txt @@ -0,0 +1,25 @@ +Copyright (c) 2019 Tokio Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-tracing-log.txt b/dist-material/licenses/LICENSE-tracing-log.txt new file mode 100644 index 0000000..cdb28b4 --- /dev/null +++ b/dist-material/licenses/LICENSE-tracing-log.txt @@ -0,0 +1,25 @@ +Copyright (c) 2019 Tokio Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-tracing-subscriber.txt b/dist-material/licenses/LICENSE-tracing-subscriber.txt new file mode 100644 index 0000000..cdb28b4 --- /dev/null +++ b/dist-material/licenses/LICENSE-tracing-subscriber.txt @@ -0,0 +1,25 @@ +Copyright (c) 2019 Tokio Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-tracing.txt b/dist-material/licenses/LICENSE-tracing.txt new file mode 100644 index 0000000..cdb28b4 --- /dev/null +++ b/dist-material/licenses/LICENSE-tracing.txt @@ -0,0 +1,25 @@ +Copyright (c) 2019 Tokio Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-try-lock.txt b/dist-material/licenses/LICENSE-try-lock.txt new file mode 100644 index 0000000..5cddb26 --- /dev/null +++ b/dist-material/licenses/LICENSE-try-lock.txt @@ -0,0 +1,21 @@ +Copyright (c) 2018 Sean McArthur +Copyright (c) 2016 Alex Crichton + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/dist-material/licenses/LICENSE-untrusted.txt b/dist-material/licenses/LICENSE-untrusted.txt new file mode 100644 index 0000000..7151db6 --- /dev/null +++ b/dist-material/licenses/LICENSE-untrusted.txt @@ -0,0 +1,13 @@ +// Copyright 2015-2016 Brian Smith. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/dist-material/licenses/LICENSE-valuable.txt b/dist-material/licenses/LICENSE-valuable.txt new file mode 100644 index 0000000..4ca822a --- /dev/null +++ b/dist-material/licenses/LICENSE-valuable.txt @@ -0,0 +1,25 @@ +Copyright (c) 2021 Valuable Contributors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-want.txt b/dist-material/licenses/LICENSE-want.txt new file mode 100644 index 0000000..e0f0f8a --- /dev/null +++ b/dist-material/licenses/LICENSE-want.txt @@ -0,0 +1,20 @@ +Copyright (c) 2018-2019 Sean McArthur + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/dist-material/licenses/LICENSE-webpki.txt b/dist-material/licenses/LICENSE-webpki.txt new file mode 100644 index 0000000..cd87be1 --- /dev/null +++ b/dist-material/licenses/LICENSE-webpki.txt @@ -0,0 +1,19 @@ +Except as otherwise noted, this project is licensed under the following +(ISC-style) terms: + +Copyright 2015 Brian Smith. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +The files under third-party/chromium are licensed as described in +third-party/chromium/LICENSE. diff --git a/dist-material/licenses/LICENSE-which.txt b/dist-material/licenses/LICENSE-which.txt new file mode 100644 index 0000000..369139b --- /dev/null +++ b/dist-material/licenses/LICENSE-which.txt @@ -0,0 +1,19 @@ +Copyright (c) 2015 fangyuanziti + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-winapi-util.txt b/dist-material/licenses/LICENSE-winapi-util.txt new file mode 100644 index 0000000..3303149 --- /dev/null +++ b/dist-material/licenses/LICENSE-winapi-util.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 Andrew Gallant + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dist-material/licenses/LICENSE-winreg.txt b/dist-material/licenses/LICENSE-winreg.txt new file mode 100644 index 0000000..b9d358e --- /dev/null +++ b/dist-material/licenses/LICENSE-winreg.txt @@ -0,0 +1,19 @@ +Copyright (c) 2015 Igor Shaula + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..825d64a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,53 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +services: + collector: + image: ghcr.io/apache/skywalking-agent-test-tool/mock-collector:f4f5ef22b1df623464772816bb6b42ba611444ff + ports: + - "19876:19876" + - "12800:12800" + healthcheck: + test: [ "CMD", "curl", "http://127.0.0.1:12800/healthCheck" ] + interval: 5s + timeout: 5s + + mysql: + image: mysql:5.7.39 + ports: + - "3306:3306" + environment: + - MYSQL_ROOT_PASSWORD=password + - MYSQL_DATABASE=skywalking + + redis: + image: bitnami/redis:7.0.4 + ports: + - "6379:6379" + environment: + - REDIS_PASSWORD=password + + memcached: + image: memcached:1.6.17 + ports: + - "11211:11211" + + rabbitmq: + image: rabbitmq:3.11.13 + ports: + - "5672:5672" + environment: + - RABBITMQ_DEFAULT_USER=guest + - RABBITMQ_DEFAULT_PASS=guest diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..7205614 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,43 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM php:8.1-fpm-bullseye as builder + +ARG SKYWALKING_AGENT + +ENV RUSTUP_HOME=/usr/local/rustup \ + CARGO_HOME=/usr/local/cargo \ + PATH=/usr/local/cargo/bin:$PATH \ + RUST_VERSION=1.64.0 + + +RUN apt update \ + && apt install -y wget protobuf-compiler libclang-dev \ + && wget https://static.rust-lang.org/rustup/archive/1.25.1/x86_64-unknown-linux-gnu/rustup-init \ + && chmod +x rustup-init \ + && ./rustup-init -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION --default-host x86_64-unknown-linux-gnu \ + && rm rustup-init \ + && chmod -R a+w $RUSTUP_HOME $CARGO_HOME \ + && pecl install skywalking_agent-$SKYWALKING_AGENT \ + && docker-php-ext-enable skywalking_agent \ + && apt-get remove -y --auto-remove wget protobuf-compiler \ + && rm -rf /var/lib/apt/lists/* + +FROM php:8.1-fpm-bullseye +LABEL org.opencontainers.image.source=https://github.com/apache/skywalking-php +LABEL org.opencontainers.image.description="The PHP Agent for Apache SkyWalking, which provides the native tracing abilities for PHP project." +LABEL org.opencontainers.image.licenses="Apache 2.0" +COPY --from=builder /usr/local/etc/php/conf.d/docker-php-ext-skywalking_agent.ini /usr/local/etc/php/conf.d/ +COPY --from=builder /usr/local/lib/php/extensions/no-debug-non-zts-20210902/skywalking_agent.so /usr/local/lib/php/extensions/no-debug-non-zts-20210902/ \ No newline at end of file diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..a6a860b --- /dev/null +++ b/docs/README.md @@ -0,0 +1,5 @@ +# SkyWalking PHP Agent + +**This is the official documentation of SkyWalking PHP Agent. Welcome to the SkyWalking community!** + +In here, you could learn how to set up PHP agent for the PHP services. diff --git a/docs/en/configuration/ini-settings.md b/docs/en/configuration/ini-settings.md new file mode 100644 index 0000000..9106753 --- /dev/null +++ b/docs/en/configuration/ini-settings.md @@ -0,0 +1,21 @@ +# INI Settings + +This is the configuration list supported in `php.ini`. + +| Configuration Item | Description | Default Value | +| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | ------------------------- | +| skywalking_agent.enable | Enable skywalking_agent extension or not. | Off | +| skywalking_agent.log_file | Log file path. | /tmp/skywalking-agent.log | +| skywalking_agent.log_level | Log level: one of `OFF`, `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`. | INFO | +| skywalking_agent.runtime_dir | Skywalking agent runtime directory. | /tmp/skywalking-agent | +| skywalking_agent.server_addr | Address of skywalking oap server. | 127.0.0.1:11800 | +| skywalking_agent.service_name | Application service name. | hello-skywalking | +| skywalking_agent.skywalking_version | Skywalking version, 8 or 9. | 8 | +| skywalking_agent.authentication | Skywalking authentication token, let it empty if the backend isn't enabled. | | +| skywalking_agent.worker_threads | Skywalking worker threads, 0 will auto set as the cpu core size. | 0 | +| skywalking_agent.enable_tls | Wether to enable tls for gPRC, default is false. | Off | +| skywalking_agent.ssl_trusted_ca_path | The gRPC SSL trusted ca file. | | +| skywalking_agent.ssl_key_path | The private key file. Enable mTLS when `ssl_key_path` and `ssl_cert_chain_path` exist. | | +| skywalking_agent.ssl_cert_chain_path | The certificate file. Enable mTLS when `ssl_key_path` and `ssl_cert_chain_path` exist. | | +| skywalking_agent.heartbeat_period | Agent heartbeat report period. Unit, second. | 30 | +| skywalking_agent.properties_report_period_factor | The agent sends the instance properties to the backend every heartbeat_period * properties_report_period_factor seconds. | 10 | diff --git a/docs/en/contribution/compiling.md b/docs/en/contribution/compiling.md new file mode 100644 index 0000000..9b03a7f --- /dev/null +++ b/docs/en/contribution/compiling.md @@ -0,0 +1,68 @@ +# Compiling project + +This document will help you compile and build the package file. + +Prepare PHP and Rust environments. + +## Install PHP Environment + +For Debian user: + +```shell +sudo apt install php-cli php-dev +``` + +For MacOS user: + +```shell +brew install php +``` + +## Install Rust Environment + +Install Rust 1.65.0+. + +For Linux user: + +```shell +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +``` + +For MacOS user: + +```shell +brew install rust +``` + +## Install requirement + +For Debian user: + +```shell +sudo apt install gcc make llvm-dev libclang-dev clang protobuf-compiler +``` + +For MacOS user: + +```shell +brew install protobuf +``` + +## Build and install Skywalking PHP Agent from archive file + +For Linux user: + +```shell +sudo pecl install skywalking_agent-x.y.z.tgz +``` + +For MacOS user: + +> Running the `pecl install` command with the php installed in brew may encounter the problem of `mkdir`, please refer to +> [Installing PHP and PECL Extensions on MacOS](https://patriqueouimet.ca/tip/installing-php-and-pecl-extensions-on-macos). + +```shell +pecl install skywalking_agent-x.y.z.tgz +``` + +The extension file `skywalking_agent.so` is generated in the php extension folder, get it by run `php-config --extension-dir`. diff --git a/docs/en/contribution/release-agent.md b/docs/en/contribution/release-agent.md new file mode 100644 index 0000000..b291799 --- /dev/null +++ b/docs/en/contribution/release-agent.md @@ -0,0 +1,176 @@ +# Apache SkyWalking PHP Agent release guide + +If you're a committer, you can learn how to release SkyWalking SDK in The Apache Way and start the voting process by +reading this document. + +## Requirements + +- Rust(rustc) +- Cargo +- PHP(php, php-config) +- Pecl +- GPG +- shasum + +## Add your GPG public key + +1. Add your GPG public key into the [SkyWalking GPG KEYS](https://dist.apache.org/repos/dist/release/skywalking/KEYS) + file. If you are a committer, use your Apache ID and password to log in this svn, and update the file. **Don't + override the existing file.**(Notice, only PMC member could update this file) +2. Upload your GPG public key to the public GPG site, such as [MIT's site](http://pgp.mit.edu:11371/). This site should + be in the Apache maven staging repository checklist. + +## Draft a new release + +Open [Create a new release](https://github.com/apache/skywalking-php/releases/new) page, choose the tag, and click the `Generate release notes` button, then copy the generated text to local `/tmp/notes.txt`. + +## Test your settings and package + +```shell +## Make sure local compiling passed +> cargo build + +## Create package.xml from package.xml.tpl +> cargo run -p scripts --release -- create-package-xml --version x.y.z --notes "`cat /tmp/notes.txt`" + +## Create local package. The skywalking_agent-x.y.z.tgz should be found in project root +> pecl package +``` + +## Sign the package + +Tag the commit ID of this release as v`x.y.z`. + +After set the version in `Cargo.toml` with the release number, package locally. Then run the following commands to sign +your package. + +```shell +> export RELEASE_VERSION=x.y.z + +## The package should be signed by your Apache committer mail. +> gpg --armor --detach-sig skywalking_agent-$RELEASE_VERSION.tgz + +> shasum -a 512 skywalking_agent-$RELEASE_VERSION.tgz > skywalking_agent-$RELEASE_VERSION.tgz.sha512 +``` + +After these, the source tar with its signed asc and sha512 are ready. + +## Upload to Apache SVN and tag a release + +1. Use your Apache ID to log in to `https://dist.apache.org/repos/dist/dev/skywalking/php`. +2. Create a folder and name it by the release version and round, such as: `x.y.z` +3. Upload tar ball, asc, sha512 files to the new folder. + +## Call a vote in dev + +Call a vote in `dev@skywalking.apache.org` + +``` +Mail title: [VOTE] Release Apache SkyWalking PHP version x.y.z + +Mail content: +Hi All, +This is a call for vote to release Apache SkyWalking PHP version x.y.z. + +Release Candidate: + +* https://dist.apache.org/repos/dist/dev/skywalking/php/x.y.z/ +* sha512 checksums +- xxxxxxxx skywalking_agent-x.y.z.tgz + +Release Tag : + +* (Git Tag) vx.y.z + +Release CommitID : + +* https://github.com/apache/skywalking-php/tree/{commit-id} + +Keys to verify the Release Candidate : + +* https://dist.apache.org/repos/dist/release/skywalking/KEYS + +Guide to build the release from source : + +* https://github.com/apache/skywalking-php/blob/master/docs/en/contribution/compiling.md + +Voting will start now (Date) and will remain open for at least 72 +hours, Request all PMC members to give their vote. +[ ] +1 Release this package. +[ ] +0 No opinion. +[ ] -1 Do not release this package because.... +``` + +## Vote Check + +The voting process is as follows: + +1. All PMC member votes are +1 binding, and all other votes are +1 but non-binding. +1. If you obtain at least 3 (+1 binding) votes with more +1 than -1 votes within 72 hours, the release will be approved. + +## Publish the release + +1. Move source codes tar and distribution packages to `https://dist.apache.org/repos/dist/release/skywalking/`. + + ```shell + > export SVN_EDITOR=vim + > svn mv https://dist.apache.org/repos/dist/dev/skywalking/php/x.y.z https://dist.apache.org/repos/dist/release/skywalking/php + .... + enter your apache password + .... + ``` + +2. Pecl publish package on [skywalking_agent](https://pecl.php.net/package/skywalking_agent). + + Make sure you have a PECL account, and list in `package.tpl.xml` as ``, + or reach `private@skywalking.apache.org` if you are a committer/PMC but not listed. + + You can request a PECL account via . + +3. Add an release event, update download and doc releases on the SkyWalking website. + +4. Add the new release on [ASF addrelease site](https://reporter.apache.org/addrelease.html?skywalking). + +5. Remove the old releases on `https://dist.apache.org/repos/dist/release/skywalking/php/{previous-version}`. + +## Send a release announcement + +Send ANNOUNCE email to `dev@skywalking.apache.org`, `announce@apache.org`. The sender should use the Apache email +account. + +```txt +Mail title: [ANNOUNCE] Apache SkyWalking PHP x.y.z released + +Mail content: +Hi all, + +SkyWalking PHP Agent provides the native tracing abilities for PHP project. + +SkyWalking: APM (application performance monitor) tool for distributed systems, +especially designed for microservices, cloud native and container-based (Docker, Kubernetes, Mesos) architectures. + +This release contains a number of new features, bug fixes and improvements compared to +version a.b.c(last release). The notable changes since x.y.z include: + +(Highlight key changes) +1. ... +2. ... +3. ... + +Apache SkyWalking website: +http://skywalking.apache.org/ + +Downloads: +http://skywalking.apache.org/downloads/ + +Twitter: +https://twitter.com/ASFSkyWalking + +SkyWalking Resources: +- GitHub: https://github.com/apache/skywalking +- Issue: https://github.com/apache/skywalking/issues +- Mailing list: dev@skywalkiing.apache.org + + +- Apache SkyWalking Team +``` diff --git a/docs/en/setup/service-agent/php-agent/README.md b/docs/en/setup/service-agent/php-agent/README.md new file mode 100644 index 0000000..3a824cc --- /dev/null +++ b/docs/en/setup/service-agent/php-agent/README.md @@ -0,0 +1,111 @@ +# Setup PHP Agent + +1. Agent is available for PHP 7.2 - 8.x. +2. Build from source. +3. Configure `php.ini`. + +## Requirements + +- GCC +- Rustc 1.56+ +- Cargo +- Libclang 9.0+ +- Make +- Protoc + +## Install dependencies + +### For Debian-base OS + +```shell +sudo apt install gcc make llvm-13-dev libclang-13-dev protobuf-c-compiler +``` + +### For Alpine Linux + +```shell +apk add gcc make musl-dev llvm15-dev clang15-dev protobuf-c-compiler +``` + +## Install Rust globally + +The officially recommended way to install Rust is via [`rustup`](https://www.rust-lang.org/tools/install). + +But because the source code toolchain is override by `rust-toolchain.toml`, +so if you don't need multi version Rust, we recommend to install Rust by these +way: + +1. Install through OS package manager (The Rust version in the source must be >= 1.65). + +2. Through [standalone installers](https://forge.rust-lang.org/infra/other-installation-methods.html#standalone-installers). + + For linux x86_64 user: + + ```shell + wget https://static.rust-lang.org/dist/rust-1.65.0-x86_64-unknown-linux-gnu.tar.gz + tar zxvf rust-1.65.0-x86_64-unknown-linux-gnu.tar.gz + cd rust-1.65.0-x86_64-unknown-linux-gnu + ./install.sh + ``` + +3. Through `rustup` but set `default-toolchain` to none. + + ```shell + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain none + ``` + +## Install + +> If you compile `skywalking_agent` in Alpine Linux, you have to disable `crt-static`, otherwise +> the problem will be throw: "the libclang shared library at /usr/lib/libclang.so.15.0.7 could not +> be opened: Dynamic loading not supported". +> +> You can disable `crt-static` by environment variable: +> +> ```shell +> export RUSTFLAGS="-C target-feature=-crt-static" +> ``` + +### Install from pecl.net + +```shell script +pecl install skywalking_agent +``` + +### Install from the source codes + +```shell script +git clone --recursive https://github.com/apache/skywalking-php.git +cd skywalking-php + +phpize +./configure +make +make install +``` + +## Configure + +Configure skywalking agent in your `php.ini`. + +```ini +[skywalking_agent] +extension=skywalking_agent.so + +; Enable skywalking_agent extension or not. +skywalking_agent.enable = On + +; Log file path. +skywalking_agent.log_file = /tmp/skywalking-agent.log + +; Log level: one of `OFF`, `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`. +skywalking_agent.log_level = INFO + +; Address of skywalking oap server. +skywalking_agent.server_addr = 127.0.0.1:11800 + +; Application service name. +skywalking_agent.service_name = hello-skywalking +``` + +Refer to the Configuration section for more configuration items. diff --git a/docs/en/setup/service-agent/php-agent/Supported-list.md b/docs/en/setup/service-agent/php-agent/Supported-list.md new file mode 100644 index 0000000..1f99cce --- /dev/null +++ b/docs/en/setup/service-agent/php-agent/Supported-list.md @@ -0,0 +1,21 @@ +# Supported SAPI, extension and library + +The following plugins provide the distributed tracing capability. + +## Supported SAPI + +* PHP-FPM +* CLI under [Swoole](https://www.swoole.com/) + +## Supported PHP extension + +* [cURL](https://www.php.net/manual/en/book.curl.php#book.curl) +* [PDO](https://www.php.net/manual/en/book.pdo.php) +* [MySQL Improved](https://www.php.net/manual/en/book.mysqli.php) +* [Memcached](https://www.php.net/manual/en/book.memcached.php) +* [phpredis](https://github.com/phpredis/phpredis) +* [php-amqplib](https://github.com/php-amqplib/php-amqplib) for Message Queuing Producer + +## Supported PHP library + +* [predis](https://github.com/predis/predis) diff --git a/docs/menu.yml b/docs/menu.yml new file mode 100644 index 0000000..63878fc --- /dev/null +++ b/docs/menu.yml @@ -0,0 +1,34 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +catalog: + - name: "Get Started" + catalog: + - name: "PHP Agent Setup" + path: "/en/setup/service-agent/php-agent/readme" + - name: "Plugins" + catalog: + - name: "Supported SAPI, extension and library" + path: "/en/setup/service-agent/php-agent/Supported-list" + - name: "Configuration" + catalog: + - name: "INI Settings" + path: "/en/configuration/ini-settings" + - name: "Contribution" + catalog: + - name: "Compiling Guidance" + path: "/en/contribution/compiling/" + - name: "PHP Agent Release Guidance" + path: "/en/contribution/release-agent/" diff --git a/package.tpl.xml b/package.tpl.xml new file mode 100644 index 0000000..9a340cc --- /dev/null +++ b/package.tpl.xml @@ -0,0 +1,76 @@ + + + + skywalking_agent + pecl.php.net + Apache SkyWalking PHP Agent. + The PHP Agent for Apache SkyWalking, which provides the native tracing abilities for PHP project. + + Apache SkyWalking + skywalking + dev@skywalking.apache.org + yes + + + + jmjoy + jmjoy + jmjoy@apache.org + yes + + + Yanlong He + yanlong + yanlong@php.net + yes + + {{ date }} + + {{ version }} + {{ version }} + + + stable + stable + + Apache-2.0 + + {{ notes }} + + + + {% for file in files %} + {% endfor %} + + + + + + 7.2.0 + + + 1.4.0 + + + + skywalking_agent + + + + diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..586fbd0 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +[toolchain] +channel = "1.65" +components = ["clippy", "rustfmt"] diff --git a/scripts/Cargo.toml b/scripts/Cargo.toml new file mode 100644 index 0000000..be50f1d --- /dev/null +++ b/scripts/Cargo.toml @@ -0,0 +1,34 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +[package] +name = "scripts" +version = "0.0.0" +authors = ["Apache Software Foundation", "jmjoy ", "Yanlong He "] +description = "The Scripts of Apache SkyWalking PHP Agent." +edition = "2021" +rust-version = "1.58" +repository = "https://github.com/apache/skywalking-php" +license = "Apache-2.0" +publish = false + +[dependencies] +anyhow = "1.0.69" +chrono = "0.4.24" +clap = { version = "4.1.8", features = ["derive"] } +serde = { version = "1.0.155", features = ["derive"] } +tera = "1.18.0" +tracing = "0.1.37" +tracing-subscriber = "0.3.16" diff --git a/scripts/src/command/create_package_xml.rs b/scripts/src/command/create_package_xml.rs new file mode 100644 index 0000000..7b4beec --- /dev/null +++ b/scripts/src/command/create_package_xml.rs @@ -0,0 +1,114 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use chrono::{DateTime, Local}; +use clap::Parser; +use serde::Serialize; +use std::{fs, path::PathBuf, process::Command, time::SystemTime}; +use tera::{Context, Tera}; +use tracing::info; + +/// Create package.xml from template file. +#[derive(Parser, Debug)] +pub struct CreatePackageXmlCommand { + /// Template file path. + #[clap(long, default_value = "./package.tpl.xml")] + tpl_path: PathBuf, + + /// Target file path. + #[clap(long, default_value = "./package.xml")] + target_path: PathBuf, + + /// Project directory path. + #[clap(long, default_value = ".")] + project_path: PathBuf, + + /// Version of skywalking_agent. + #[clap(long)] + version: String, + + /// Release date, default is current local timezone date. + #[clap(long)] + date: Option, + + /// Release notes. + #[clap(long)] + notes: String, +} + +#[derive(Serialize)] +struct File { + name: String, + role: String, +} + +impl File { + fn new(path: &str) -> Self { + let path = path.trim_matches('"'); + let role = if path.ends_with(".md") + || path.starts_with("docs/") + || path.starts_with("dist-material/") + || ["LICENSE", "NOTICE"].contains(&path) + { + "doc" + } else { + "src" + }; + + Self { + name: path.to_owned(), + role: role.to_owned(), + } + } +} + +impl CreatePackageXmlCommand { + pub fn run(&self) -> anyhow::Result<()> { + info!(tpl_path = ?&self.tpl_path, "read template content"); + let tpl = fs::read_to_string(&self.tpl_path)?; + + let mut context = Context::new(); + context.insert("date", &self.get_date()); + context.insert("version", &self.version); + context.insert("notes", &self.notes); + context.insert("files", &self.get_git_files()?); + + let mut tera = Tera::default(); + let contents = tera.render_str(&tpl, &context)?; + + info!(target_path = ?&self.target_path, "write target content"); + fs::write(&self.target_path, contents)?; + + Ok(()) + } + + fn get_date(&self) -> String { + match &self.date { + Some(date) => date.to_owned(), + None => { + let datetime: DateTime = SystemTime::now().into(); + datetime.format("%Y-%m-%d").to_string() + } + } + } + + fn get_git_files(&self) -> anyhow::Result> { + let output = Command::new("git") + .args(["ls-tree", "-r", "HEAD", "--name-only"]) + .output()?; + let content = String::from_utf8(output.stdout)?; + Ok(content.split_whitespace().map(File::new).collect()) + } +} diff --git a/scripts/src/command/mod.rs b/scripts/src/command/mod.rs new file mode 100644 index 0000000..ab291be --- /dev/null +++ b/scripts/src/command/mod.rs @@ -0,0 +1,32 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod create_package_xml; + +use self::create_package_xml::CreatePackageXmlCommand; +use clap::Subcommand; + +#[derive(Subcommand, Debug)] +pub enum Commands { + CreatePackageXml(CreatePackageXmlCommand), +} + +impl Commands { + pub fn run(&self) -> anyhow::Result<()> { + match self { + Commands::CreatePackageXml(cmd) => cmd.run(), + } + } +} diff --git a/scripts/src/main.rs b/scripts/src/main.rs new file mode 100644 index 0000000..0d814bd --- /dev/null +++ b/scripts/src/main.rs @@ -0,0 +1,49 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod command; + +use crate::command::Commands; +use anyhow::Context; +use clap::Parser; +use tracing::metadata::LevelFilter; +use tracing_subscriber::FmtSubscriber; + +/// Args. +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct Args { + /// Log level. + #[clap(long, default_value = "INFO")] + log_level: LevelFilter, + + #[clap(subcommand)] + command: Commands, +} + +fn setup_log(args: &Args) -> anyhow::Result<()> { + let subscriber = FmtSubscriber::builder() + .with_max_level(args.log_level) + .finish(); + + tracing::subscriber::set_global_default(subscriber).context("setting default subscriber failed") +} + +fn main() -> anyhow::Result<()> { + let args = Args::parse(); + setup_log(&args)?; + args.command.run()?; + Ok(()) +} diff --git a/src/channel.rs b/src/channel.rs new file mode 100644 index 0000000..e29617b --- /dev/null +++ b/src/channel.rs @@ -0,0 +1,95 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use anyhow::anyhow; +use once_cell::sync::OnceCell; +use skywalking::reporter::{CollectItem, Report}; +use std::{ + io::Write, + mem::size_of, + ops::DerefMut, + os::unix::net::UnixStream, + path::{Path, PathBuf}, + sync::Mutex, +}; +use tokio::{io::AsyncReadExt, sync::mpsc}; +use tracing::error; + +fn channel_send(data: CollectItem, mut sender: T) -> anyhow::Result<()> +where + T: DerefMut, +{ + let content = bincode::serialize(&data)?; + + sender.write_all(&content.len().to_le_bytes())?; + sender.write_all(&content)?; + sender.flush()?; + + Ok(()) +} + +pub async fn channel_receive(receiver: &mut tokio::net::UnixStream) -> anyhow::Result { + let mut size_buf = [0u8; size_of::()]; + receiver.read_exact(&mut size_buf).await?; + let size = usize::from_le_bytes(size_buf); + + let mut content = vec![0u8; size]; + receiver.read_exact(&mut content).await?; + + let item = bincode::deserialize(&content)?; + Ok(item) +} + +pub struct Reporter { + worker_addr: PathBuf, + stream: OnceCell>, +} + +impl Reporter { + pub fn new(worker_addr: impl AsRef) -> Self { + Self { + worker_addr: worker_addr.as_ref().to_path_buf(), + stream: OnceCell::new(), + } + } + + fn try_report(&self, item: CollectItem) -> anyhow::Result<()> { + let stream = self + .stream + .get_or_try_init(|| UnixStream::connect(&self.worker_addr).map(Mutex::new))? + .lock() + .map_err(|_| anyhow!("Get Lock failed"))?; + + channel_send(item, stream) + } +} + +impl Report for Reporter { + fn report(&self, item: CollectItem) { + if let Err(err) = self.try_report(item) { + error!(?err, "channel send failed"); + } + } +} + +pub struct TxReporter(pub mpsc::Sender); + +impl Report for TxReporter { + fn report(&self, item: CollectItem) { + if let Err(err) = self.0.try_send(item) { + error!(?err, "Send collect item failed"); + } + } +} diff --git a/src/component.rs b/src/component.rs new file mode 100644 index 0000000..6e42e71 --- /dev/null +++ b/src/component.rs @@ -0,0 +1,27 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License.. + +//! Component ID +//! +//! + +pub const COMPONENT_PHP_ID: i32 = 8001; +pub const COMPONENT_PHP_CURL_ID: i32 = 8002; +pub const COMPONENT_PHP_PDO_ID: i32 = 8003; +pub const COMPONENT_PHP_MYSQLI_ID: i32 = 8004; +pub const COMPONENT_PHP_PREDIS_ID: i32 = 8006; +pub const COMPONENT_PHP_MEMCACHED_ID: i32 = 20; +pub const COMPONENT_PHP_REDIS_ID: i32 = 7; +pub const COMPONENT_AMQP_PRODUCER_ID: i32 = 144; diff --git a/src/context.rs b/src/context.rs new file mode 100644 index 0000000..181efaa --- /dev/null +++ b/src/context.rs @@ -0,0 +1,72 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use anyhow::anyhow; +use dashmap::DashMap; +use once_cell::sync::Lazy; +use skywalking::trace::{ + propagation::encoder::encode_propagation, span::Span, trace_context::TracingContext, +}; + +pub const SW_HEADER: &str = "sw8"; + +static REQUEST_CONTEXT: Lazy, RequestContext>> = Lazy::new(DashMap::new); + +pub struct RequestContext { + pub tracing_context: TracingContext, + pub entry_span: Span, +} + +impl RequestContext { + pub fn set_global(request_id: Option, ctx: Self) { + REQUEST_CONTEXT.insert(request_id, ctx); + } + + pub fn remove_global(request_id: Option) -> Option { + REQUEST_CONTEXT.remove(&request_id).map(|(_, ctx)| ctx) + } + + pub fn try_with_global( + request_id: Option, f: impl FnOnce(&mut RequestContext) -> anyhow::Result, + ) -> anyhow::Result { + REQUEST_CONTEXT + .get_mut(&request_id) + .map(|mut ctx| f(ctx.value_mut())) + .transpose()? + .ok_or_else(|| anyhow!("global tracing context not exists")) + } + + pub fn try_with_global_ctx( + request_id: Option, f: impl FnOnce(&mut TracingContext) -> anyhow::Result, + ) -> anyhow::Result { + Self::try_with_global(request_id, |ctx| f(&mut ctx.tracing_context)) + } + + pub fn try_get_sw_header(request_id: Option) -> crate::Result { + Ok(Self::try_with_global(request_id, |req_ctx| { + let span_object = req_ctx.get_primary_span().span_object(); + Ok(encode_propagation( + &req_ctx.tracing_context, + &span_object.operation_name, + &span_object.peer, + )) + })?) + } + + /// Primary endpoint name is used for endpoint dependency. + fn get_primary_span(&self) -> &Span { + &self.entry_span + } +} diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 0000000..4de992a --- /dev/null +++ b/src/errors.rs @@ -0,0 +1,46 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use anyhow::anyhow; +use std::{result, str::Utf8Error}; + +pub type Result = result::Result; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error(transparent)] + PHPer(#[from] phper::Error), + + #[error(transparent)] + Anyhow(#[from] anyhow::Error), +} + +impl From for Error { + fn from(e: Utf8Error) -> Self { + Self::Anyhow(e.into()) + } +} + +impl From for Error { + fn from(e: url::ParseError) -> Self { + Self::Anyhow(e.into()) + } +} + +impl From for Error { + fn from(e: String) -> Self { + Self::Anyhow(anyhow!("{}", e)) + } +} diff --git a/src/execute.rs b/src/execute.rs new file mode 100644 index 0000000..4bc8e68 --- /dev/null +++ b/src/execute.rs @@ -0,0 +1,326 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{ + plugin::select_plugin, + request::{HACK_SWOOLE_ON_REQUEST_FUNCTION_NAME, IS_SWOOLE}, + util::catch_unwind_result, +}; +use anyhow::{bail, Context}; +use phper::{ + objects::ZObj, + strings::ZStr, + sys, + values::{ExecuteData, ZVal}, +}; +use std::{any::Any, panic::AssertUnwindSafe, ptr::null_mut, sync::atomic::Ordering}; +use tracing::{error, trace}; + +pub type BeforeExecuteHook = + dyn FnOnce(Option, &mut ExecuteData) -> crate::Result>; + +pub type AfterExecuteHook = + dyn FnOnce(Option, Box, &mut ExecuteData, &mut ZVal) -> crate::Result<()>; + +pub trait Noop { + fn noop() -> Self; +} + +impl Noop for Box { + #[inline] + fn noop() -> Self { + fn f(_: Option, _: &mut ExecuteData) -> crate::Result> { + Ok(Box::new(())) + } + Box::new(f) + } +} + +impl Noop for Box { + #[inline] + fn noop() -> Self { + fn f( + _: Option, _: Box, _: &mut ExecuteData, _: &mut ZVal, + ) -> crate::Result<()> { + Ok(()) + } + Box::new(f) + } +} + +static mut ORI_EXECUTE_INTERNAL: Option< + unsafe extern "C" fn(execute_data: *mut sys::zend_execute_data, return_value: *mut sys::zval), +> = None; + +static mut ORI_EXECUTE_EX: Option = + None; + +unsafe extern "C" fn execute_internal( + execute_data: *mut sys::zend_execute_data, return_value: *mut sys::zval, +) { + let (execute_data, return_value) = match ( + ExecuteData::try_from_mut_ptr(execute_data), + ZVal::try_from_mut_ptr(return_value), + ) { + (Some(execute_data), Some(return_value)) => (execute_data, return_value), + (execute_data, return_value) => { + ori_execute_internal(execute_data, return_value); + return; + } + }; + + let (function_name, class_name) = match get_function_and_class_name(execute_data) { + Ok(x) => x, + Err(err) => { + error!(?err, "get function and class name failed"); + ori_execute_internal(Some(execute_data), Some(return_value)); + return; + } + }; + + trace!( + ?function_name, + ?class_name, + "execute_internal function and class name" + ); + + let function_name = match function_name { + Some(function_name) => function_name, + None => { + ori_execute_internal(Some(execute_data), Some(return_value)); + return; + } + }; + + if function_name == HACK_SWOOLE_ON_REQUEST_FUNCTION_NAME { + ori_execute_internal(Some(execute_data), Some(return_value)); + return; + } + + let plugin = select_plugin(class_name.as_deref(), &function_name); + let plugin = match plugin { + Some(plugin) => plugin, + None => { + ori_execute_internal(Some(execute_data), Some(return_value)); + return; + } + }; + + let (before, after) = match plugin.hook(class_name.as_deref(), &function_name) { + Some(hook) => hook, + None => { + ori_execute_internal(Some(execute_data), Some(return_value)); + return; + } + }; + + let request_id = infer_request_id(execute_data); + trace!( + ?request_id, + ?function_name, + ?class_name, + "execute_internal infer request id" + ); + + let result = catch_unwind_result(AssertUnwindSafe(|| before(request_id, execute_data))); + if let Err(err) = &result { + error!(?err, "before execute internal"); + } + + ori_execute_internal(Some(execute_data), Some(return_value)); + + // If before hook return error, don't execute the after hook. + if let Ok(data) = result { + if let Err(err) = catch_unwind_result(AssertUnwindSafe(|| { + after(request_id, data, execute_data, return_value) + })) { + error!(?err, "after execute internal"); + } + } +} + +unsafe extern "C" fn execute_ex(execute_data: *mut sys::zend_execute_data) { + let execute_data = match ExecuteData::try_from_mut_ptr(execute_data) { + Some(execute_data) => execute_data, + None => { + ori_execute_ex(None); + return; + } + }; + + let (function_name, class_name) = match get_function_and_class_name(execute_data) { + Ok(x) => x, + Err(err) => { + error!(?err, "get function and class name failed"); + ori_execute_ex(Some(execute_data)); + return; + } + }; + + trace!( + ?function_name, + ?class_name, + "execute_ex function and class name" + ); + + let function_name = match function_name { + Some(function_name) => function_name, + None => { + ori_execute_ex(Some(execute_data)); + return; + } + }; + + let plugin = select_plugin(class_name.as_deref(), &function_name); + let plugin = match plugin { + Some(plugin) => plugin, + None => { + ori_execute_ex(Some(execute_data)); + return; + } + }; + + let (before, after) = match plugin.hook(class_name.as_deref(), &function_name) { + Some(hook) => hook, + None => { + ori_execute_ex(Some(execute_data)); + return; + } + }; + + let request_id = infer_request_id(execute_data); + trace!( + ?request_id, + ?function_name, + ?class_name, + "execute_ex infer request id" + ); + + let result = catch_unwind_result(AssertUnwindSafe(|| before(request_id, execute_data))); + if let Err(err) = &result { + error!(?err, "before execute ex"); + } + + ori_execute_ex(Some(execute_data)); + + // If before hook return error, don't execute the after hook. + if let Ok(data) = result { + let mut null = ZVal::from(()); + let return_value = match ZVal::try_from_mut_ptr((*execute_data.as_mut_ptr()).return_value) { + Some(return_value) => return_value, + None => &mut null, + }; + if let Err(err) = catch_unwind_result(AssertUnwindSafe(|| { + after(request_id, data, execute_data, return_value) + })) { + error!(?err, "after execute ex"); + } + } +} + +#[inline] +fn ori_execute_internal(execute_data: Option<&mut ExecuteData>, return_value: Option<&mut ZVal>) { + let execute_data = execute_data + .map(ExecuteData::as_mut_ptr) + .unwrap_or(null_mut()); + let return_value = return_value.map(ZVal::as_mut_ptr).unwrap_or(null_mut()); + unsafe { + match ORI_EXECUTE_INTERNAL { + Some(f) => f(execute_data, return_value), + None => sys::execute_internal(execute_data, return_value), + } + } +} + +#[inline] +fn ori_execute_ex(execute_data: Option<&mut ExecuteData>) { + unsafe { + if let Some(f) = ORI_EXECUTE_EX { + f(execute_data + .map(ExecuteData::as_mut_ptr) + .unwrap_or(null_mut())) + } + } +} + +pub fn register_execute_functions() { + unsafe { + ORI_EXECUTE_INTERNAL = sys::zend_execute_internal; + sys::zend_execute_internal = Some(execute_internal); + + ORI_EXECUTE_EX = sys::zend_execute_ex; + sys::zend_execute_ex = Some(execute_ex); + } +} + +pub fn validate_num_args(execute_data: &mut ExecuteData, num: usize) -> anyhow::Result<()> { + if execute_data.num_args() < num { + bail!("argument count incorrect"); + } + Ok(()) +} + +pub fn get_this_mut(execute_data: &mut ExecuteData) -> anyhow::Result<&mut ZObj> { + execute_data.get_this_mut().context("$this is empty") +} + +fn get_function_and_class_name( + execute_data: &mut ExecuteData, +) -> anyhow::Result<(Option, Option)> { + let function = execute_data.func(); + + let function_name = function + .get_function_name() + .map(ZStr::to_str) + .transpose()? + .map(ToOwned::to_owned); + let class_name = function + .get_class() + .map(|cls| cls.get_name().to_str().map(ToOwned::to_owned)) + .transpose()?; + + Ok((function_name, class_name)) +} + +fn infer_request_id(execute_data: &mut ExecuteData) -> Option { + if !IS_SWOOLE.load(Ordering::Relaxed) { + return None; + } + + let mut prev_execute_data_ptr = execute_data.as_mut_ptr(); + loop { + let Some(prev_execute_data) = (unsafe { ExecuteData::try_from_mut_ptr(prev_execute_data_ptr) }) else { + return None; + }; + let func_name = prev_execute_data.func().get_function_name(); + if !func_name + .map(|s| s == &HACK_SWOOLE_ON_REQUEST_FUNCTION_NAME.as_bytes()) + .unwrap_or_default() + { + prev_execute_data_ptr = unsafe { (*prev_execute_data_ptr).prev_execute_data }; + continue; + } + let Some(request) = prev_execute_data.get_mut_parameter(0).as_mut_z_obj() else { + return None; + }; + match request.get_mut_property("fd").as_long() { + Some(fd) => return Some(fd), + None => { + error!("infer request id failed"); + return None; + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..27b211e --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,180 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![allow(missing_docs)] +#![warn(rust_2018_idioms)] +#![warn(clippy::dbg_macro, clippy::print_stdout)] + +mod channel; +mod component; +mod context; +mod errors; +mod execute; +mod module; +mod plugin; +mod request; +mod tag; +mod util; +mod worker; + +use phper::{ini::Policy, modules::Module, php_get_module}; +use phper::values::ZVal; +use skywalking::common::random_generator::RandomGenerator; + +use crate::request::HACK_SWOOLE_ON_REQUEST_FUNCTION_NAME; +pub use errors::{Error, Result}; + +/// Enable agent and report or not. +const SKYWALKING_AGENT_ENABLE: &str = "skywalking_agent.enable"; + +/// Version of skywalking server. +const SKYWALKING_AGENT_SKYWALKING_VERSION: &str = "skywalking_agent.skywalking_version"; + +/// skywalking server address. +const SKYWALKING_AGENT_SERVER_ADDR: &str = "skywalking_agent.server_addr"; + +/// skywalking app service name. +const SKYWALKING_AGENT_SERVICE_NAME: &str = "skywalking_agent.service_name"; + +/// Tokio runtime worker threads. +const SKYWALKING_AGENT_WORKER_THREADS: &str = "skywalking_agent.worker_threads"; + +/// Log level of skywalking agent. +const SKYWALKING_AGENT_LOG_LEVEL: &str = "skywalking_agent.log_level"; + +/// Log file of skywalking agent. +const SKYWALKING_AGENT_LOG_FILE: &str = "skywalking_agent.log_file"; + +/// Skywalking agent runtime directory. +const SKYWALKING_AGENT_RUNTIME_DIR: &str = "skywalking_agent.runtime_dir"; + +/// Skywalking agent authentication token. +const SKYWALKING_AGENT_AUTHENTICATION: &str = "skywalking_agent.authentication"; + +/// Wether to enable tls for gPRC. +const SKYWALKING_AGENT_ENABLE_TLS: &str = "skywalking_agent.enable_tls"; + +/// The gRPC SSL trusted ca file. +const SKYWALKING_AGENT_SSL_TRUSTED_CA_PATH: &str = "skywalking_agent.ssl_trusted_ca_path"; + +/// The private key file. Enable mTLS when ssl_key_path and ssl_cert_chain_path +/// exist. +const SKYWALKING_AGENT_SSL_KEY_PATH: &str = "skywalking_agent.ssl_key_path"; + +/// The certificate file. Enable mTLS when ssl_key_path and ssl_cert_chain_path +/// exist. +const SKYWALKING_AGENT_SSL_CERT_CHAIN_PATH: &str = "skywalking_agent.ssl_cert_chain_path"; + +/// Agent heartbeat report period. Unit, second. +const SKYWALKING_AGENT_HEARTBEAT_PERIOD: &str = "skywalking_agent.heartbeat_period"; + +/// The agent sends the instance properties to the backend every +/// heartbeat_period * properties_report_period_factor seconds. +const SKYWALKING_AGENT_PROPERTIES_REPORT_PERIOD_FACTOR: &str = + "skywalking_agent.properties_report_period_factor"; + +fn random(arguments: &mut [ZVal]) -> phper::Result { + // Get the first argument, expect the type `ZStr`, and convert to Rust utf-8 + // str. + let prefix = arguments[0].expect_z_str()?.to_str()?; + // unsafe {sys::api_module.putenv_handler("abc=1", 6)}; + // Macro which do php internal `echo`. + let string = format!("{}-{}", prefix, RandomGenerator::generate()); + + Ok(string) +} + +#[php_get_module] +pub fn get_module() -> Module { + let mut module = Module::new( + env!("CARGO_CRATE_NAME"), + env!("CARGO_PKG_VERSION"), + env!("CARGO_PKG_AUTHORS"), + ); + + // Register skywalking ini. + module.add_ini(SKYWALKING_AGENT_ENABLE, false, Policy::System); + module.add_ini(SKYWALKING_AGENT_SKYWALKING_VERSION, 8i64, Policy::System); + module.add_ini( + SKYWALKING_AGENT_SERVER_ADDR, + "127.0.0.1:11800".to_string(), + Policy::System, + ); + module.add_ini( + SKYWALKING_AGENT_SERVICE_NAME, + "hello-skywalking".to_string(), + Policy::System, + ); + module.add_ini(SKYWALKING_AGENT_WORKER_THREADS, 0i64, Policy::System); + module.add_ini( + SKYWALKING_AGENT_LOG_LEVEL, + "OFF".to_string(), + Policy::System, + ); + module.add_ini( + SKYWALKING_AGENT_LOG_FILE, + "/tmp/skywalking-agent.log".to_string(), + Policy::System, + ); + module.add_ini( + SKYWALKING_AGENT_RUNTIME_DIR, + "/tmp/skywalking-agent".to_string(), + Policy::System, + ); + module.add_ini( + SKYWALKING_AGENT_AUTHENTICATION, + "".to_string(), + Policy::System, + ); + module.add_ini(SKYWALKING_AGENT_ENABLE_TLS, false, Policy::System); + module.add_ini( + SKYWALKING_AGENT_SSL_TRUSTED_CA_PATH, + "".to_string(), + Policy::System, + ); + module.add_ini( + SKYWALKING_AGENT_SSL_KEY_PATH, + "".to_string(), + Policy::System, + ); + module.add_ini( + SKYWALKING_AGENT_SSL_CERT_CHAIN_PATH, + "".to_string(), + Policy::System, + ); + module.add_ini(SKYWALKING_AGENT_HEARTBEAT_PERIOD, 30i64, Policy::System); + module.add_ini( + SKYWALKING_AGENT_PROPERTIES_REPORT_PERIOD_FACTOR, + 10i64, + Policy::System, + ); + + // Hooks. + module.on_module_init(module::init); + module.on_module_shutdown(module::shutdown); + module.on_request_init(request::init); + module.on_request_shutdown(request::shutdown); + + // The function is used by swoole plugin, to surround the callback of on + // request. + module.add_function( + HACK_SWOOLE_ON_REQUEST_FUNCTION_NAME, + request::skywalking_hack_swoole_on_request, + ); + + module.add_function("random_str", random); + + module +} diff --git a/src/module.rs b/src/module.rs new file mode 100644 index 0000000..4480d17 --- /dev/null +++ b/src/module.rs @@ -0,0 +1,261 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{ + channel::Reporter, + execute::register_execute_functions, + util::{get_sapi_module_name, IPS}, + worker::init_worker, + SKYWALKING_AGENT_AUTHENTICATION, SKYWALKING_AGENT_ENABLE, SKYWALKING_AGENT_ENABLE_TLS, + SKYWALKING_AGENT_HEARTBEAT_PERIOD, SKYWALKING_AGENT_LOG_FILE, SKYWALKING_AGENT_LOG_LEVEL, + SKYWALKING_AGENT_PROPERTIES_REPORT_PERIOD_FACTOR, SKYWALKING_AGENT_RUNTIME_DIR, + SKYWALKING_AGENT_SERVICE_NAME, SKYWALKING_AGENT_SKYWALKING_VERSION, + SKYWALKING_AGENT_SSL_CERT_CHAIN_PATH, SKYWALKING_AGENT_SSL_KEY_PATH, + SKYWALKING_AGENT_SSL_TRUSTED_CA_PATH, +}; +use anyhow::bail; +use once_cell::sync::Lazy; +use phper::{arrays::ZArr, ini::ini_get, sys}; +use skywalking::{ + common::random_generator::RandomGenerator, + trace::tracer::{self, Tracer}, +}; +use std::{ + borrow::ToOwned, + ffi::{CStr, OsStr}, + fs::{self, OpenOptions}, + os::unix::prelude::OsStrExt, + path::{Path, PathBuf}, + str::FromStr, + time::SystemTime, +}; +use tracing::{debug, error, info, metadata::LevelFilter}; +use tracing_subscriber::FmtSubscriber; + +pub static SERVICE_NAME: Lazy = Lazy::new(|| { + ini_get::>(SKYWALKING_AGENT_SERVICE_NAME) + .and_then(|s| s.to_str().ok()) + .map(ToOwned::to_owned) + .unwrap_or_default() +}); + +pub static SERVICE_INSTANCE: Lazy = + Lazy::new(|| RandomGenerator::generate() + "@" + &IPS[0]); + +pub static SKYWALKING_VERSION: Lazy = + Lazy::new(|| ini_get::(SKYWALKING_AGENT_SKYWALKING_VERSION)); + +pub static RUNTIME_DIR: Lazy = Lazy::new(|| { + let mut path = PathBuf::new(); + if let Some(dir) = ini_get::>(SKYWALKING_AGENT_RUNTIME_DIR) { + let dir = dir.to_bytes(); + if !dir.is_empty() { + path.push(OsStr::from_bytes(dir)); + } + } + path +}); + +pub static SOCKET_FILE_PATH: Lazy = Lazy::new(|| { + let mut dir = RUNTIME_DIR.clone(); + + let dur = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .expect("Get timestamp failed") + .as_micros(); + + dir.push(format!("{:x}.sock", dur)); + + dir +}); + +pub static AUTHENTICATION: Lazy = Lazy::new(|| { + ini_get::>(SKYWALKING_AGENT_AUTHENTICATION) + .and_then(|s| s.to_str().ok()) + .map(ToOwned::to_owned) + .unwrap_or_default() +}); + +pub static ENABLE_TLS: Lazy = Lazy::new(|| ini_get::(SKYWALKING_AGENT_ENABLE_TLS)); + +pub static SSL_TRUSTED_CA_PATH: Lazy = Lazy::new(|| { + ini_get::>(SKYWALKING_AGENT_SSL_TRUSTED_CA_PATH) + .and_then(|s| s.to_str().ok()) + .map(ToOwned::to_owned) + .unwrap_or_default() +}); + +pub static SSL_KEY_PATH: Lazy = Lazy::new(|| { + ini_get::>(SKYWALKING_AGENT_SSL_KEY_PATH) + .and_then(|s| s.to_str().ok()) + .map(ToOwned::to_owned) + .unwrap_or_default() +}); + +pub static SSL_CERT_CHAIN_PATH: Lazy = Lazy::new(|| { + ini_get::>(SKYWALKING_AGENT_SSL_CERT_CHAIN_PATH) + .and_then(|s| s.to_str().ok()) + .map(ToOwned::to_owned) + .unwrap_or_default() +}); + +pub static HEARTBEAT_PERIOD: Lazy = + Lazy::new(|| ini_get::(SKYWALKING_AGENT_HEARTBEAT_PERIOD)); + +pub static PROPERTIES_REPORT_PERIOD_FACTOR: Lazy = + Lazy::new(|| ini_get::(SKYWALKING_AGENT_PROPERTIES_REPORT_PERIOD_FACTOR)); + +pub fn init() { + if !is_enable() { + return; + } + + if let Err(err) = try_init_logger() { + eprintln!("skywalking_agent: initialize logger failed: {}", err); + } + + // Skywalking agent info. + let service_name = Lazy::force(&SERVICE_NAME); + let service_instance = Lazy::force(&SERVICE_INSTANCE); + let skywalking_version = Lazy::force(&SKYWALKING_VERSION); + let authentication = Lazy::force(&AUTHENTICATION); + let heartbeat_period = Lazy::force(&HEARTBEAT_PERIOD); + let properties_report_period_factor = Lazy::force(&PROPERTIES_REPORT_PERIOD_FACTOR); + info!( + service_name, + service_instance, + skywalking_version, + authentication, + heartbeat_period, + properties_report_period_factor, + "Starting skywalking agent" + ); + + // Skywalking version check. + if *skywalking_version < 8 { + error!( + skywalking_version, + "The skywalking agent only supports versions after skywalking 8" + ); + return; + } + + // Initialize TLS if enabled. + let enable_tls = Lazy::force(&ENABLE_TLS); + let ssl_trusted_ca_path = Lazy::force(&SSL_TRUSTED_CA_PATH); + let ssl_key_path = Lazy::force(&SSL_KEY_PATH); + let ssl_cert_chain_path = Lazy::force(&SSL_CERT_CHAIN_PATH); + debug!( + enable_tls, + ssl_trusted_ca_path, ssl_key_path, ssl_cert_chain_path, "Skywalking TLS info" + ); + + // Initialize runtime directory. + if RUNTIME_DIR.as_os_str().is_empty() { + error!("The skywalking agent runtime directory must not be empty"); + return; + } + if let Err(err) = fs::create_dir_all(&*RUNTIME_DIR) { + error!(?err, "Create runtime directory failed"); + return; + } + + // Initialize Agent worker. + Lazy::force(&SOCKET_FILE_PATH); + init_worker(); + + tracer::set_global_tracer(Tracer::new( + service_name, + service_instance, + Reporter::new(&*SOCKET_FILE_PATH), + )); + + // Hook functions. + register_execute_functions(); +} + +pub fn shutdown() { + if !is_enable() { + return; + } + + info!("Shutdowning skywalking agent"); +} + +fn try_init_logger() -> anyhow::Result<()> { + let log_level = ini_get::>(SKYWALKING_AGENT_LOG_LEVEL) + .and_then(|s| s.to_str().ok()) + .unwrap_or("OFF"); + let log_level = log_level.trim(); + + let log_level = LevelFilter::from_str(log_level)?; + if log_level == LevelFilter::OFF { + return Ok(()); + } + + let log_file = ini_get::>(SKYWALKING_AGENT_LOG_FILE) + .and_then(|s| s.to_str().ok()) + .unwrap_or_default(); + let log_file = log_file.trim(); + if log_file.is_empty() { + bail!("log file cant't be empty when log enabled"); + } + + let path = Path::new(log_file); + + if let Some(parent) = path.parent() { + fs::create_dir_all(parent)?; + } + + let mut open_options = OpenOptions::new(); + open_options.append(true).create(true); + + let file = open_options.open(path)?; + + let subscriber = FmtSubscriber::builder() + .with_max_level(log_level) + .with_ansi(false) + .with_writer(file) + .finish(); + + tracing::subscriber::set_global_default(subscriber)?; + + Ok(()) +} + +fn get_module_registry() -> &'static ZArr { + unsafe { ZArr::from_ptr(&sys::module_registry) } +} + +pub fn is_enable() -> bool { + static IS_ENABLE: Lazy = Lazy::new(|| { + if !ini_get::(SKYWALKING_AGENT_ENABLE) { + return false; + } + + let sapi = get_sapi_module_name().to_bytes(); + + if sapi == b"fpm-fcgi" { + return true; + } + + if sapi == b"cli" && get_module_registry().exists("swoole") { + return true; + } + + false + }); + *IS_ENABLE +} diff --git a/src/plugin/mod.rs b/src/plugin/mod.rs new file mode 100644 index 0000000..8826c2b --- /dev/null +++ b/src/plugin/mod.rs @@ -0,0 +1,76 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod plugin_amqplib; +mod plugin_curl; +mod plugin_memcached; +mod plugin_mysqli; +mod plugin_pdo; +mod plugin_predis; +mod plugin_redis; +mod plugin_swoole; + +use crate::execute::{AfterExecuteHook, BeforeExecuteHook}; +use once_cell::sync::Lazy; + +// Register plugins here. +static PLUGINS: Lazy>> = Lazy::new(|| { + vec![ + Box::::default(), + Box::::default(), + Box::::default(), + Box::::default(), + Box::::default(), + Box::::default(), + Box::::default(), + Box::::default(), + Box::::default(), + ] +}); + +pub type DynPlugin = dyn Plugin + Send + Sync + 'static; + +pub trait Plugin { + fn class_names(&self) -> Option<&'static [&'static str]>; + + fn function_name_prefix(&self) -> Option<&'static str>; + + fn hook( + &self, class_name: Option<&str>, function_name: &str, + ) -> Option<(Box, Box)>; +} + +pub fn select_plugin(class_name: Option<&str>, function_name: &str) -> Option<&'static DynPlugin> { + let mut selected_plugin = None; + + for plugin in &*PLUGINS { + if let Some(class_name) = class_name { + if let Some(plugin_class_names) = plugin.class_names() { + if plugin_class_names.contains(&class_name) { + selected_plugin = Some(plugin); + break; + } + } + } + if let Some(function_name_prefix) = plugin.function_name_prefix() { + if function_name.starts_with(function_name_prefix) { + selected_plugin = Some(plugin); + break; + } + } + } + + selected_plugin.map(AsRef::as_ref) +} diff --git a/src/plugin/plugin_amqplib.rs b/src/plugin/plugin_amqplib.rs new file mode 100644 index 0000000..e6065a8 --- /dev/null +++ b/src/plugin/plugin_amqplib.rs @@ -0,0 +1,177 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::Plugin; +use crate::{ + component::COMPONENT_AMQP_PRODUCER_ID, + context::{RequestContext, SW_HEADER}, + execute::{get_this_mut, validate_num_args, AfterExecuteHook, BeforeExecuteHook, Noop}, + tag::{TAG_MQ_BROKER, TAG_MQ_QUEUE, TAG_MQ_TOPIC}, +}; +use anyhow::Context; +use phper::{ + arrays::ZArray, + classes::ClassEntry, + functions::call, + objects::{ZObj, ZObject}, + values::{ExecuteData, ZVal}, +}; +use skywalking::{skywalking_proto::v3::SpanLayer, trace::span::Span}; + +#[derive(Default, Clone)] +pub struct AmqplibPlugin; + +impl Plugin for AmqplibPlugin { + fn class_names(&self) -> Option<&'static [&'static str]> { + Some(&["PhpAmqpLib\\Channel\\AMQPChannel"]) + } + + fn function_name_prefix(&self) -> Option<&'static str> { + None + } + + fn hook( + &self, class_name: Option<&str>, function_name: &str, + ) -> Option<( + Box, + Box, + )> { + match (class_name, function_name) { + ( + Some(class_name @ "PhpAmqpLib\\Channel\\AMQPChannel"), + function_name @ "basic_publish", + ) => Some(self.hook_channel_basic_publish(class_name, function_name)), + _ => None, + } + } +} + +impl AmqplibPlugin { + fn hook_channel_basic_publish( + &self, class_name: &str, function_name: &str, + ) -> (Box, Box) { + let class_name = class_name.to_owned(); + let function_name = function_name.to_owned(); + ( + Box::new(move |request_id, execute_data| { + validate_num_args(execute_data, 3)?; + + let this = get_this_mut(execute_data)?; + + let peer = Self::get_peer(this); + + let exchange = execute_data + .get_parameter(1) + .as_z_str() + .and_then(|s| s.to_str().ok()) + .map(ToOwned::to_owned) + .unwrap_or_else(|| "unknown".to_owned()); + + let routing_key = execute_data + .get_parameter(2) + .as_z_str() + .and_then(|s| s.to_str().ok()) + .map(ToOwned::to_owned) + .unwrap_or_else(|| "unknown".to_owned()); + + let span = Self::create_exit_span( + request_id, + &class_name, + &function_name, + &peer, + &exchange, + &routing_key, + )?; + + Self::inject_sw_header(request_id, execute_data)?; + + Ok(Box::new(span)) + }), + Noop::noop(), + ) + } + + fn get_peer(this: &mut ZObj) -> String { + let Some(io) = this.get_property("connection").as_z_obj().and_then(|connection| connection.get_property("io").as_z_obj()) else { + return "unknown:0".to_owned(); + }; + let host = io + .get_property("host") + .as_z_str() + .and_then(|s| s.to_str().ok()) + .unwrap_or("unknown"); + let port = io.get_property("port").as_long().unwrap_or_default(); + format!("{}:{}", host, port) + } + + fn create_exit_span( + request_id: Option, class_name: &str, function_name: &str, peer: &str, exchange: &str, + routing_key: &str, + ) -> crate::Result { + let mut span = RequestContext::try_with_global_ctx(request_id, |ctx| { + Ok(ctx.create_exit_span(&format!("{}->{}", class_name, function_name), peer)) + })?; + + let mut span_object = span.span_object_mut(); + span_object.set_span_layer(SpanLayer::Mq); + span_object.component_id = COMPONENT_AMQP_PRODUCER_ID; + span_object.add_tag(TAG_MQ_BROKER, peer); + span_object.add_tag(TAG_MQ_TOPIC, exchange); + span_object.add_tag(TAG_MQ_QUEUE, routing_key); + drop(span_object); + + Ok(span) + } + + fn inject_sw_header( + request_id: Option, execute_data: &mut ExecuteData, + ) -> crate::Result<()> { + const HEADER_NAME: &str = "application_headers"; + + let sw_header = RequestContext::try_get_sw_header(request_id)?; + + let message = execute_data + .get_mut_parameter(0) + .as_mut_z_obj() + .context("message isn't object")?; + + let has = message + .call("has", [ZVal::from(HEADER_NAME)])? + .expect_bool()?; + if has { + let mut headers = message.call("get", [ZVal::from(HEADER_NAME)])?; + let headers = headers.expect_mut_z_obj()?; + headers.call("set", [ZVal::from(SW_HEADER), ZVal::from(sw_header)])?; + } else { + let headers = Self::new_sw_headers(&sw_header)?; + message.call("set", [ZVal::from(HEADER_NAME), ZVal::from(headers)])?; + } + + Ok(()) + } + + fn new_sw_headers(sw_header: &str) -> crate::Result { + let mut arr = ZArray::new(); + arr.insert(SW_HEADER, sw_header); + + let class_name = "PhpAmqpLib\\Wire\\AMQPTable"; + let exists = call("class_exists", [ZVal::from(class_name), ZVal::from(true)])?; + if !exists.as_bool().unwrap_or_default() { + return Err(format!("Class {} not exists", class_name).into()); + } + let obj = ClassEntry::from_globals(class_name)?.new_object([ZVal::from(arr)])?; + Ok(obj) + } +} diff --git a/src/plugin/plugin_curl.rs b/src/plugin/plugin_curl.rs new file mode 100644 index 0000000..7ca08f5 --- /dev/null +++ b/src/plugin/plugin_curl.rs @@ -0,0 +1,461 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::Plugin; +use crate::{ + component::COMPONENT_PHP_CURL_ID, + context::{RequestContext, SW_HEADER}, + execute::{validate_num_args, AfterExecuteHook, BeforeExecuteHook, Noop}, +}; +use anyhow::Context; +use phper::{ + arrays::{InsertKey, ZArray}, + functions::call, + values::{ExecuteData, ZVal}, +}; +use skywalking::trace::span::Span; +use std::{cell::RefCell, collections::HashMap, os::raw::c_long}; +use tracing::{debug, warn}; +use url::Url; + +const CURLM_OK: i64 = 0; + +const CURLOPT_HTTPHEADER: c_long = 10023; + +/// Prevent calling `curl_setopt` inside this plugin sets headers, the hook of +/// `curl_setopt` is repeatedly called. +const SKY_CURLOPT_HTTPHEADER: c_long = 9923; + +thread_local! { + static CURL_HEADERS: RefCell> = Default::default(); + static CURL_MULTI_INFO_MAP: RefCell> = Default::default(); +} + +struct CurlInfo { + cid: i64, + raw_url: String, + url: Url, + peer: String, + is_http: bool, +} + +#[derive(Default)] +struct CurlMultiInfo { + exec_spans: Option>, + curl_handles: HashMap, +} + +impl CurlMultiInfo { + fn insert_curl_handle(&mut self, id: i64, handle: ZVal) { + self.curl_handles.insert(id, handle); + } + + fn remove_curl_handle(&mut self, id: i64) { + self.curl_handles.remove(&id); + } +} + +#[derive(Default, Clone)] +pub struct CurlPlugin; + +impl Plugin for CurlPlugin { + #[inline] + fn class_names(&self) -> Option<&'static [&'static str]> { + None + } + + #[inline] + fn function_name_prefix(&self) -> Option<&'static str> { + Some("curl_") + } + + fn hook( + &self, _class_name: Option<&str>, function_name: &str, + ) -> Option<(Box, Box)> { + match function_name { + "curl_setopt" => Some(self.hook_curl_setopt()), + "curl_setopt_array" => Some(self.hook_curl_setopt_array()), + "curl_exec" => Some(self.hook_curl_exec()), + "curl_close" => Some(self.hook_curl_close()), + + "curl_multi_add_handle" => Some(self.hook_curl_multi_add_handle()), + "curl_multi_remove_handle" => Some(self.hook_curl_multi_remove_handle()), + "curl_multi_exec" => Some(self.hook_curl_multi_exec()), + "curl_multi_close" => Some(self.hook_curl_multi_close()), + + _ => None, + } + } +} + +impl CurlPlugin { + fn hook_curl_setopt(&self) -> (Box, Box) { + ( + Box::new(|_, execute_data| { + validate_num_args(execute_data, 3)?; + + let cid = Self::get_resource_id(execute_data)?; + let options = execute_data.get_parameter(1).as_long(); + + if options == Some(SKY_CURLOPT_HTTPHEADER) { + *execute_data.get_mut_parameter(1) = CURLOPT_HTTPHEADER.into(); + } else if options == Some(CURLOPT_HTTPHEADER) { + let value = execute_data.get_parameter(2); + if value.get_type_info().is_array() { + CURL_HEADERS + .with(|headers| headers.borrow_mut().insert(cid, value.clone())); + } + } + + Ok(Box::new(())) + }), + Noop::noop(), + ) + } + + fn hook_curl_setopt_array(&self) -> (Box, Box) { + ( + Box::new(|_, execute_data| { + validate_num_args(execute_data, 2)?; + + let cid = Self::get_resource_id(execute_data)?; + + if let Some(opts) = execute_data.get_parameter(1).as_z_arr() { + if let Some(value) = opts.get(CURLOPT_HTTPHEADER as u64) { + CURL_HEADERS + .with(|headers| headers.borrow_mut().insert(cid, value.clone())); + } + } + + Ok(Box::new(())) + }), + Noop::noop(), + ) + } + + fn hook_curl_exec(&self) -> (Box, Box) { + ( + Box::new(|request_id, execute_data| { + validate_num_args(execute_data, 1)?; + + let cid = Self::get_resource_id(execute_data)?; + let ch = execute_data.get_parameter(0); + + let info = Self::get_curl_info(cid, ch.clone())?; + + let span = Self::create_exit_span(request_id, &info)?; + + if info.is_http { + Self::inject_sw_header(request_id, ch.clone(), &info)?; + } + + Ok(Box::new(span)) + }), + Box::new(move |_, span, execute_data, _| { + let mut span = span.downcast::().unwrap(); + + let ch = execute_data.get_parameter(0); + Self::finish_exit_span(&mut span, ch)?; + + Ok(()) + }), + ) + } + + fn hook_curl_close(&self) -> (Box, Box) { + ( + Box::new(|_, execute_data| { + validate_num_args(execute_data, 1)?; + + let cid = Self::get_resource_id(execute_data)?; + + CURL_HEADERS.with(|headers| headers.borrow_mut().remove(&cid)); + + Ok(Box::new(())) + }), + Noop::noop(), + ) + } + + fn hook_curl_multi_add_handle(&self) -> (Box, Box) { + ( + Box::new(|_, execute_data| { + validate_num_args(execute_data, 2)?; + + let multi_id = Self::get_resource_id(execute_data)?; + let ch = execute_data.get_parameter(1); + let cid = Self::get_handle_id(ch)?; + + CURL_MULTI_INFO_MAP.with(|map| { + map.borrow_mut() + .entry(multi_id) + .or_default() + .insert_curl_handle(cid, ch.clone()); + }); + + Ok(Box::new(())) + }), + Noop::noop(), + ) + } + + fn hook_curl_multi_remove_handle(&self) -> (Box, Box) { + ( + Box::new(|_, execute_data| { + validate_num_args(execute_data, 2)?; + + let multi_id = Self::get_resource_id(execute_data)?; + let ch = execute_data.get_parameter(1); + let cid = Self::get_handle_id(ch)?; + + CURL_MULTI_INFO_MAP.with(|map| { + map.borrow_mut() + .entry(multi_id) + .or_default() + .remove_curl_handle(cid); + }); + + Ok(Box::new(())) + }), + Noop::noop(), + ) + } + + fn hook_curl_multi_exec(&self) -> (Box, Box) { + ( + Box::new(|request_id, execute_data| { + validate_num_args(execute_data, 1)?; + + let multi_id = Self::get_resource_id(execute_data)?; + + let is_exec = CURL_MULTI_INFO_MAP.with(|map| { + let mut map = map.borrow_mut(); + let Some(multi_info) = map.get_mut(&multi_id) else { + debug!(multi_id, "curl multi info is missing, maybe hasn't handles"); + return Ok(false); + }; + + debug!(multi_id, "curl multi handles count: {}", multi_info.curl_handles.len()); + if multi_info.curl_handles.is_empty() { + return Ok(false); + } + if multi_info.exec_spans.is_some() { + return Ok(true); + } + + let mut curl_infos = Vec::with_capacity(multi_info.curl_handles.len()); + for (cid, ch) in &multi_info.curl_handles { + curl_infos.push( (*cid, ch.clone(), Self::get_curl_info(*cid, ch.clone())?)); + } + curl_infos.sort_by(|(_, _, i1), (_, _, i2)| i1.raw_url.cmp(&i2.raw_url)); + + let mut exec_spans = Vec::with_capacity(curl_infos.len()); + for (cid, ch, info) in curl_infos { + let span = Self::create_exit_span(request_id, &info)?; + + if info.is_http { + Self::inject_sw_header(request_id, ch, &info)?; + } + + debug!(multi_id, operation_name = ?&span.span_object().operation_name, "create exit span"); + exec_spans.push((cid, span)); + } + + // skywalking-rust can't create same level span at one time, so modify parent + // span id by hand. + if let [(_, head_span), tail_span @ ..] = exec_spans.as_mut_slice() { + let parent_span_id = head_span.span_object().parent_span_id; + for (_, span) in tail_span { + span.span_object_mut().parent_span_id = parent_span_id; + } + } + + multi_info.exec_spans = Some(exec_spans); + + Ok::<_, crate::Error>(true) + })?; + + Ok(Box::new(is_exec)) + }), + Box::new(move |_, is_exec, execute_data, return_value| { + let is_exec = is_exec.downcast::().unwrap(); + if !*is_exec { + return Ok(()); + } + + if return_value.as_long() != Some(CURLM_OK) { + return Ok(()); + } + + let still_running = execute_data.get_parameter(1); + if still_running + .as_z_ref() + .map(|r| r.val()) + .and_then(|val| val.as_long()) + != Some(0) + { + return Ok(()); + } + + let multi_id = Self::get_resource_id(execute_data)?; + debug!(multi_id, "curl multi exec has finished"); + + CURL_MULTI_INFO_MAP.with(|map| { + let Some(mut info) = map.borrow_mut().remove(&multi_id) else { + warn!(multi_id, "curl multi info is missing after finished"); + return Ok(()); + }; + let Some(mut spans) = info.exec_spans else { + warn!(multi_id, "curl multi spans is missing after finished"); + return Ok(()); + }; + + debug!(multi_id, "curl multi spans count: {}", spans.len()); + loop { + let Some((cid, mut span)) = spans.pop() else { break }; + let Some(ch) = info.curl_handles.remove(&cid) else { continue }; + Self::finish_exit_span(&mut span, &ch)?; + } + Ok::<_, crate::Error>(()) + })?; + + Ok(()) + }), + ) + } + + fn hook_curl_multi_close(&self) -> (Box, Box) { + ( + Box::new(|_, execute_data| { + validate_num_args(execute_data, 1)?; + + let multi_id = Self::get_resource_id(execute_data)?; + + CURL_MULTI_INFO_MAP.with(|map| map.borrow_mut().remove(&multi_id)); + + Ok(Box::new(())) + }), + Noop::noop(), + ) + } + + fn get_resource_id(execute_data: &mut ExecuteData) -> anyhow::Result { + let ch = execute_data.get_parameter(0); + Self::get_handle_id(ch) + } + + fn get_handle_id(ch: &ZVal) -> anyhow::Result { + // The `curl_init` return object since PHP8. + ch.as_z_res() + .map(|res| res.handle()) + .or_else(|| ch.as_z_obj().map(|obj| obj.handle().into())) + .context("Get resource id failed") + } + + fn get_curl_info(cid: i64, ch: ZVal) -> crate::Result { + let result = call("curl_getinfo", &mut [ch])?; + let result = result.as_z_arr().context("result isn't array")?; + + let url = result + .get("url") + .context("Get url from curl_get_info result failed")?; + let raw_url = url.as_z_str().context("url isn't string")?.to_str()?; + let mut url = raw_url.to_string(); + + if !url.contains("://") { + url.insert_str(0, "http://"); + } + + let url: Url = url.parse().context("parse url")?; + let is_http = ["http", "https"].contains(&url.scheme()); + + debug!("curl_getinfo get url: {}", &url); + + let host = url.host_str().unwrap_or_default(); + let port = match url.port() { + Some(port) => port, + None => match url.scheme() { + "http" => 80, + "https" => 443, + _ => 0, + }, + }; + let peer = format!("{host}:{port}"); + + Ok(CurlInfo { + cid, + raw_url: raw_url.to_string(), + url, + peer, + is_http, + }) + } + + fn inject_sw_header(request_id: Option, ch: ZVal, info: &CurlInfo) -> crate::Result<()> { + let sw_header = RequestContext::try_get_sw_header(request_id)?; + let mut val = CURL_HEADERS + .with(|headers| headers.borrow_mut().remove(&info.cid)) + .unwrap_or_else(|| ZVal::from(ZArray::new())); + if let Some(arr) = val.as_mut_z_arr() { + arr.insert( + InsertKey::NextIndex, + ZVal::from(format!("{}: {}", SW_HEADER, sw_header)), + ); + call( + "curl_setopt", + &mut [ch, ZVal::from(SKY_CURLOPT_HTTPHEADER), val], + )?; + } + Ok(()) + } + + fn create_exit_span(request_id: Option, info: &CurlInfo) -> crate::Result { + let mut span = RequestContext::try_with_global_ctx(request_id, |ctx| { + Ok(ctx.create_exit_span(info.url.path(), &info.peer)) + })?; + + let mut span_object = span.span_object_mut(); + span_object.component_id = COMPONENT_PHP_CURL_ID; + span_object.add_tag("url", &info.raw_url); + drop(span_object); + + Ok(span) + } + + fn finish_exit_span(span: &mut Span, ch: &ZVal) -> crate::Result<()> { + let result = call("curl_getinfo", &mut [ch.clone()])?; + let response = result.as_z_arr().context("response in not arr")?; + let http_code = response + .get("http_code") + .and_then(|code| code.as_long()) + .context("Call curl_getinfo, http_code is null")?; + span.add_tag("status_code", &*http_code.to_string()); + if http_code == 0 { + let result = call("curl_error", &mut [ch.clone()])?; + let curl_error = result + .as_z_str() + .context("curl_error is not string")? + .to_str()?; + let mut span_object = span.span_object_mut(); + span_object.is_error = true; + span_object.add_log(vec![("CURL_ERROR", curl_error)]); + } else if http_code >= 400 { + span.span_object_mut().is_error = true; + } else { + span.span_object_mut().is_error = false; + } + Ok(()) + } +} diff --git a/src/plugin/plugin_memcached.rs b/src/plugin/plugin_memcached.rs new file mode 100644 index 0000000..48f4cf6 --- /dev/null +++ b/src/plugin/plugin_memcached.rs @@ -0,0 +1,384 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::{any::Any, collections::HashMap}; + +use super::Plugin; +use crate::{ + component::COMPONENT_PHP_MEMCACHED_ID, + context::RequestContext, + execute::{get_this_mut, AfterExecuteHook, BeforeExecuteHook}, + tag::{CacheOp, TAG_CACHE_CMD, TAG_CACHE_KEY, TAG_CACHE_OP, TAG_CACHE_TYPE}, +}; +use anyhow::Context; +use once_cell::sync::Lazy; +use phper::{ + objects::ZObj, + values::{ExecuteData, ZVal}, +}; +use skywalking::{skywalking_proto::v3::SpanLayer, trace::span::Span}; +use tracing::{debug, instrument, warn}; + +/// The method parameters is empty. +static MEMCACHE_EMPTY_METHOD_MAPPING: Lazy>> = Lazy::new(|| { + [ + ("getallkeys", TagInfo::new(None, None)), + ("getstats", TagInfo::new(Some("stats"), None)), + ("flush", TagInfo::new(None, None)), + ("getversion", TagInfo::new(Some("version"), None)), + ] + .into_iter() + .collect() +}); + +/// The method first parameter is key. +static MEMCACHE_KEY_METHOD_MAPPING: Lazy>> = Lazy::new(|| { + [ + ("set", TagInfo::new(Some("set"), Some(CacheOp::Write))), + ("setmulti", TagInfo::new(Some("set"), Some(CacheOp::Write))), + ("add", TagInfo::new(Some("add"), Some(CacheOp::Write))), + ( + "replace", + TagInfo::new(Some("replace"), Some(CacheOp::Write)), + ), + ("append", TagInfo::new(Some("append"), Some(CacheOp::Write))), + ( + "prepend", + TagInfo::new(Some("prepend"), Some(CacheOp::Write)), + ), + ("get", TagInfo::new(Some("get"), Some(CacheOp::Read))), + ("getmulti", TagInfo::new(Some("get"), Some(CacheOp::Read))), + ("delete", TagInfo::new(Some("delete"), Some(CacheOp::Write))), + ( + "deletemulti", + TagInfo::new(Some("deleteMulti"), Some(CacheOp::Write)), + ), + ( + "increment", + TagInfo::new(Some("increment"), Some(CacheOp::Write)), + ), + ( + "decrement", + TagInfo::new(Some("decrement"), Some(CacheOp::Write)), + ), + ] + .into_iter() + .collect() +}); + +/// The method first parameter is server key and second parameter is key. +static MEMCACHE_SERVER_KEY_METHOD_MAPPING: Lazy>> = + Lazy::new(|| { + [ + ("setByKey", TagInfo::new(Some("set"), Some(CacheOp::Write))), + ( + "setMultiByKey", + TagInfo::new(Some("set"), Some(CacheOp::Write)), + ), + ("addByKey", TagInfo::new(Some("add"), Some(CacheOp::Write))), + ( + "replaceByKey", + TagInfo::new(Some("replace"), Some(CacheOp::Write)), + ), + ( + "appendByKey", + TagInfo::new(Some("append"), Some(CacheOp::Write)), + ), + ( + "prependByKey", + TagInfo::new(Some("prepend"), Some(CacheOp::Write)), + ), + ("getByKey", TagInfo::new(Some("get"), Some(CacheOp::Read))), + ( + "getMultiByKey", + TagInfo::new(Some("get"), Some(CacheOp::Read)), + ), + ( + "deleteByKey", + TagInfo::new(Some("delete"), Some(CacheOp::Write)), + ), + ( + "deleteMultiByKey", + TagInfo::new(Some("deleteMulti"), Some(CacheOp::Write)), + ), + ( + "incrementByKey", + TagInfo::new(Some("increment"), Some(CacheOp::Write)), + ), + ( + "decrementByKey", + TagInfo::new(Some("decrement"), Some(CacheOp::Write)), + ), + ] + .into_iter() + .collect() + }); + +struct TagInfo<'a> { + cmd: Option<&'a str>, + op: Option, +} + +impl<'a> TagInfo<'a> { + fn new(cmd: Option<&'a str>, op: Option) -> Self { + Self { cmd, op } + } +} + +#[derive(Default, Clone)] +pub struct MemcachedPlugin; + +impl Plugin for MemcachedPlugin { + fn class_names(&self) -> Option<&'static [&'static str]> { + Some(&["Memcached"]) + } + + fn function_name_prefix(&self) -> Option<&'static str> { + None + } + + fn hook( + &self, class_name: Option<&str>, function_name: &str, + ) -> Option<( + Box, + Box, + )> { + match (class_name, function_name) { + (Some(class_name @ "Memcached"), f) + if MEMCACHE_EMPTY_METHOD_MAPPING.contains_key(&*f.to_ascii_lowercase()) => + { + Some(self.hook_memcached_empty_methods(class_name, function_name)) + } + (Some(class_name @ "Memcached"), f) + if MEMCACHE_KEY_METHOD_MAPPING.contains_key(&*f.to_ascii_lowercase()) => + { + Some(self.hook_memcached_key_methods(class_name, function_name)) + } + (Some(class_name @ "Memcached"), f) + if MEMCACHE_SERVER_KEY_METHOD_MAPPING.contains_key(&*f.to_ascii_lowercase()) => + { + Some(self.hook_memcached_server_key_methods(class_name, function_name)) + } + _ => None, + } + } +} + +impl MemcachedPlugin { + #[instrument(skip_all)] + fn hook_memcached_empty_methods( + &self, class_name: &str, function_name: &str, + ) -> (Box, Box) { + let class_name = class_name.to_owned(); + let function_name = function_name.to_owned(); + ( + Box::new(move |request_id, _| { + let tag_info = MEMCACHE_EMPTY_METHOD_MAPPING + .get(&*function_name.to_ascii_lowercase()) + .unwrap(); + + let span = + create_exit_span(request_id, &class_name, &function_name, "", tag_info, None)?; + + Ok(Box::new(span)) + }), + Box::new(after_hook), + ) + } + + #[instrument(skip_all)] + fn hook_memcached_key_methods( + &self, class_name: &str, function_name: &str, + ) -> (Box, Box) { + let class_name = class_name.to_owned(); + let function_name = function_name.to_owned(); + ( + Box::new(move |request_id, execute_data| { + let key = { + let key = execute_data.get_parameter(0); + if key.get_type_info().is_string() { + Some(key.clone()) + } else { + // The `*Multi` methods will failed here. + warn!("The argument key of {} isn't string", &function_name); + None + } + }; + + let key_str = key + .as_ref() + .and_then(|key| key.as_z_str()) + .and_then(|key| key.to_str().ok()) + .map(ToOwned::to_owned); + + let this = get_this_mut(execute_data)?; + + let peer = key.map(|key| get_peer(this, key)).unwrap_or_default(); + + debug!(peer, "Get memcached peer"); + + let tag_info = MEMCACHE_KEY_METHOD_MAPPING + .get(&*function_name.to_ascii_lowercase()) + .unwrap(); + + let span = create_exit_span( + request_id, + &class_name, + &function_name, + &peer, + tag_info, + key_str.as_deref(), + )?; + + Ok(Box::new(span)) + }), + Box::new(after_hook), + ) + } + + #[instrument(skip_all)] + fn hook_memcached_server_key_methods( + &self, class_name: &str, function_name: &str, + ) -> (Box, Box) { + let class_name = class_name.to_owned(); + let function_name = function_name.to_owned(); + ( + Box::new(move |request_id, execute_data| { + let server_key = { + let server_key = execute_data.get_parameter(0); + if server_key.get_type_info().is_string() { + Some(server_key.clone()) + } else { + // The `*Multi` methods will failed here. + warn!(function_name, "The argument server_key isn't string"); + None + } + }; + + let key = execute_data + .get_parameter(1) + .as_z_str() + .and_then(|key| key.to_str().ok()) + .map(ToOwned::to_owned); + + let this = get_this_mut(execute_data)?; + + let peer = server_key + .map(|server_key| get_peer(this, server_key)) + .unwrap_or_default(); + + debug!(peer, "Get memcached peer"); + + let tag_info = MEMCACHE_SERVER_KEY_METHOD_MAPPING + .get(&*function_name.to_ascii_lowercase()) + .unwrap(); + + let span = create_exit_span( + request_id, + &class_name, + &function_name, + &peer, + tag_info, + key.as_deref(), + )?; + + Ok(Box::new(span)) + }), + Box::new(after_hook), + ) + } +} + +#[instrument(skip_all)] +fn after_hook( + _: Option, span: Box, execute_data: &mut ExecuteData, return_value: &mut ZVal, +) -> crate::Result<()> { + let mut span = span.downcast::().expect("Downcast to Span failed"); + if let Some(b) = return_value.as_bool() { + if !b { + span.span_object_mut().is_error = true; + + let this = get_this_mut(execute_data)?; + let code = this.call(&"getResultCode".to_ascii_lowercase(), [])?; + let code = code.as_long().context("ResultCode isn't int")?; + debug!(code, "get memcached result code"); + + if code != 0 { + let message = this.call(&"getResultMessage".to_ascii_lowercase(), [])?; + let message = message + .as_z_str() + .context("ResultMessage isn't string")? + .to_str()?; + debug!(message, "get memcached result message"); + + span.add_log([ + ("ResultCode", code.to_string()), + ("ResultMessage", message.to_owned()), + ]); + } + } + } + Ok(()) +} + +fn create_exit_span<'a>( + request_id: Option, class_name: &str, function_name: &str, remote_peer: &str, + tag_info: &TagInfo<'a>, key: Option<&str>, +) -> anyhow::Result { + RequestContext::try_with_global_ctx(request_id, |ctx| { + let mut span = + ctx.create_exit_span(&format!("{}->{}", class_name, function_name), remote_peer); + + let mut span_object = span.span_object_mut(); + span_object.set_span_layer(SpanLayer::Cache); + span_object.component_id = COMPONENT_PHP_MEMCACHED_ID; + span_object.add_tag(TAG_CACHE_TYPE, "memcache"); + if let Some(cmd) = tag_info.cmd { + span_object.add_tag(TAG_CACHE_CMD, cmd); + } + if let Some(op) = &tag_info.op { + span_object.add_tag(TAG_CACHE_OP, op.to_string()); + }; + if let Some(key) = key { + span_object.add_tag(TAG_CACHE_KEY, key) + } + drop(span_object); + + Ok(span) + }) +} + +fn get_peer(this: &mut ZObj, key: ZVal) -> String { + let f = || { + let info = this.call(&"getServerByKey".to_ascii_lowercase(), [key])?; + let info = info.as_z_arr().context("Server isn't array")?; + let host = info + .get("host") + .context("Server host not exists")? + .as_z_str() + .context("Server host isn't string")? + .to_str()?; + let port = info + .get("port") + .context("Server port not exists")? + .as_long() + .context("Server port isn't long")?; + Ok::<_, crate::Error>(format!("{}:{}", host, port)) + }; + f().unwrap_or_else(|err| { + warn!(?err, "Get peer failed"); + "".to_owned() + }) +} diff --git a/src/plugin/plugin_mysqli.rs b/src/plugin/plugin_mysqli.rs new file mode 100644 index 0000000..b3f1dfc --- /dev/null +++ b/src/plugin/plugin_mysqli.rs @@ -0,0 +1,180 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::Plugin; +use crate::{ + component::COMPONENT_PHP_MYSQLI_ID, + context::RequestContext, + execute::{get_this_mut, AfterExecuteHook, BeforeExecuteHook, Noop}, +}; +use anyhow::Context; +use dashmap::DashMap; +use once_cell::sync::Lazy; +use phper::{objects::ZObj, sys}; +use skywalking::{skywalking_proto::v3::SpanLayer, trace::span::Span}; +use tracing::debug; + +static MYSQL_MAP: Lazy> = Lazy::new(Default::default); + +static DTOR_MAP: Lazy> = Lazy::new(Default::default); + +#[derive(Default, Clone)] +pub struct MySQLImprovedPlugin; + +impl Plugin for MySQLImprovedPlugin { + #[inline] + fn class_names(&self) -> Option<&'static [&'static str]> { + Some(&["mysqli"]) + } + + #[inline] + fn function_name_prefix(&self) -> Option<&'static str> { + None + } + + fn hook( + &self, class_name: Option<&str>, function_name: &str, + ) -> Option<(Box, Box)> { + match (class_name, function_name) { + (Some("mysqli"), "__construct") => Some(self.hook_mysqli_construct()), + (Some("mysqli"), f) if ["query"].contains(&f) => { + Some(self.hook_mysqli_methods(function_name)) + } + _ => None, + } + } +} + +impl MySQLImprovedPlugin { + fn hook_mysqli_construct(&self) -> (Box, Box) { + ( + Box::new(|_, execute_data| { + let this = get_this_mut(execute_data)?; + let handle = this.handle(); + hack_dtor(this, Some(mysqli_dtor)); + + let mut info: MySQLInfo = MySQLInfo { + hostname: "127.0.0.1".to_string(), + port: 3306, + }; + + let num_args = execute_data.num_args(); + if num_args >= 1 { + // host only + let hostname = execute_data.get_parameter(0); + let hostname = hostname + .as_z_str() + .context("hostname isn't str")? + .to_str()?; + debug!(hostname, "mysqli hostname"); + + info.hostname = hostname.to_owned(); + } + if num_args >= 5 { + let port = execute_data.get_parameter(4); + let port = port.as_long().context("port isn't str")?; + debug!(port, "mysqli port"); + info.port = port + } + + MYSQL_MAP.insert(handle, info); + Ok(Box::new(())) + }), + Noop::noop(), + ) + } + + fn hook_mysqli_methods( + &self, function_name: &str, + ) -> (Box, Box) { + let function_name = function_name.to_owned(); + ( + Box::new(move |request_id, execute_data| { + let this = get_this_mut(execute_data)?; + let handle = this.handle(); + + debug!(handle, function_name, "call mysqli method"); + + let mut span = with_info(handle, |info| { + create_mysqli_exit_span(request_id, "mysqli", &function_name, info) + })?; + + if execute_data.num_args() >= 1 { + if let Some(statement) = execute_data.get_parameter(0).as_z_str() { + span.add_tag("db.statement", statement.to_str()?); + } + } + + Ok(Box::new(span) as _) + }), + Noop::noop(), + ) + } +} + +fn create_mysqli_exit_span( + request_id: Option, class_name: &str, function_name: &str, info: &MySQLInfo, +) -> anyhow::Result { + RequestContext::try_with_global_ctx(request_id, |ctx| { + let mut span = ctx.create_exit_span( + &format!("{}->{}", class_name, function_name), + &format!("{}:{}", info.hostname, info.port), + ); + + let mut span_object = span.span_object_mut(); + span_object.set_span_layer(SpanLayer::Database); + span_object.component_id = COMPONENT_PHP_MYSQLI_ID; + span_object.add_tag("db.type", "mysql"); + drop(span_object); + + Ok(span) + }) +} + +fn with_info(handle: u32, f: impl FnOnce(&MySQLInfo) -> anyhow::Result) -> anyhow::Result { + MYSQL_MAP + .get(&handle) + .map(|r| f(r.value())) + .context("info not exists")? +} + +struct MySQLInfo { + hostname: String, + port: i64, +} + +fn hack_dtor(this: &mut ZObj, new_dtor: sys::zend_object_dtor_obj_t) { + let handle = this.handle(); + + unsafe { + let ori_dtor = (*(*this.as_mut_ptr()).handlers).dtor_obj; + DTOR_MAP.insert(handle, ori_dtor); + (*((*this.as_mut_ptr()).handlers as *mut sys::zend_object_handlers)).dtor_obj = new_dtor; + } +} + +unsafe extern "C" fn mysqli_dtor(object: *mut sys::zend_object) { + debug!("call mysqli dtor"); + dtor(object); +} + +unsafe extern "C" fn dtor(object: *mut sys::zend_object) { + let handle = ZObj::from_ptr(object).handle(); + + MYSQL_MAP.remove(&handle); + if let Some((_, Some(dtor))) = DTOR_MAP.remove(&handle) { + dtor(object); + } +} diff --git a/src/plugin/plugin_pdo.rs b/src/plugin/plugin_pdo.rs new file mode 100644 index 0000000..1f31b56 --- /dev/null +++ b/src/plugin/plugin_pdo.rs @@ -0,0 +1,331 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::Plugin; +use crate::{ + component::COMPONENT_PHP_PDO_ID, + context::RequestContext, + execute::{get_this_mut, validate_num_args, AfterExecuteHook, BeforeExecuteHook, Noop}, + tag::{TAG_DB_STATEMENT, TAG_DB_TYPE}, +}; +use anyhow::Context; +use dashmap::DashMap; +use once_cell::sync::Lazy; +use phper::{ + arrays::ZArr, + objects::ZObj, + sys, + values::{ExecuteData, ZVal}, +}; +use skywalking::{skywalking_proto::v3::SpanLayer, trace::span::Span}; +use std::{any::Any, str::FromStr}; +use tracing::{debug, warn}; + +static DSN_MAP: Lazy> = Lazy::new(Default::default); +static DTOR_MAP: Lazy> = Lazy::new(Default::default); + +#[derive(Default, Clone)] +pub struct PdoPlugin; + +impl Plugin for PdoPlugin { + fn class_names(&self) -> Option<&'static [&'static str]> { + Some(&["PDO", "PDOStatement"]) + } + + fn function_name_prefix(&self) -> Option<&'static str> { + None + } + + fn hook( + &self, class_name: Option<&str>, function_name: &str, + ) -> Option<( + Box, + Box, + )> { + match (class_name, function_name) { + (Some("PDO"), "__construct") => Some(self.hook_pdo_construct()), + (Some("PDO"), f) + if [ + "exec", + "query", + "prepare", + "commit", + "begintransaction", + "rollback", + ] + .contains(&f) => + { + Some(self.hook_pdo_methods(function_name)) + } + (Some("PDOStatement"), f) + if ["execute", "fetch", "fetchAll", "fetchColumn", "fetchObject"].contains(&f) => + { + Some(self.hook_pdo_statement_methods(function_name)) + } + _ => None, + } + } +} + +impl PdoPlugin { + fn hook_pdo_construct(&self) -> (Box, Box) { + ( + Box::new(|_, execute_data| { + validate_num_args(execute_data, 1)?; + + let this = get_this_mut(execute_data)?; + let handle = this.handle(); + hack_dtor(this, Some(pdo_dtor)); + + let dsn = execute_data.get_parameter(0); + let dsn = dsn.as_z_str().context("dsn isn't str")?.to_str()?; + debug!(dsn, "construct PDO"); + + let dsn: Dsn = dsn.parse()?; + debug!(?dsn, "parse PDO dsn"); + + DSN_MAP.insert(handle, dsn); + + Ok(Box::new(())) + }), + Noop::noop(), + ) + } + + fn hook_pdo_methods( + &self, function_name: &str, + ) -> (Box, Box) { + let function_name = function_name.to_owned(); + ( + Box::new(move |request_id, execute_data| { + let handle = get_this_mut(execute_data)?.handle(); + + debug!(handle, function_name, "call PDO method"); + + let mut span = with_dsn(handle, |dsn| { + create_exit_span_with_dsn(request_id, "PDO", &function_name, dsn) + })?; + + if execute_data.num_args() >= 1 { + if let Some(statement) = execute_data.get_parameter(0).as_z_str() { + span.add_tag(TAG_DB_STATEMENT, statement.to_str()?); + } + } + + Ok(Box::new(span) as _) + }), + Box::new(after_hook), + ) + } + + fn hook_pdo_statement_methods( + &self, function_name: &str, + ) -> (Box, Box) { + let function_name = function_name.to_owned(); + ( + Box::new(move |request_id, execute_data| { + let this = get_this_mut(execute_data)?; + let handle = this.handle(); + + debug!(handle, function_name, "call PDOStatement method"); + + let mut span = with_dsn(handle, |dsn| { + create_exit_span_with_dsn(request_id, "PDOStatement", &function_name, dsn) + })?; + + if let Some(query) = this.get_property("queryString").as_z_str() { + span.add_tag(TAG_DB_STATEMENT, query.to_str()?); + } else { + warn!("PDOStatement queryString is empty"); + } + + Ok(Box::new(span) as _) + }), + Box::new(after_hook), + ) + } +} + +fn hack_dtor(this: &mut ZObj, new_dtor: sys::zend_object_dtor_obj_t) { + let handle = this.handle(); + + unsafe { + let ori_dtor = (*(*this.as_mut_ptr()).handlers).dtor_obj; + DTOR_MAP.insert(handle, ori_dtor); + (*((*this.as_mut_ptr()).handlers as *mut sys::zend_object_handlers)).dtor_obj = new_dtor; + } +} + +unsafe extern "C" fn pdo_dtor(object: *mut sys::zend_object) { + debug!("call PDO dtor"); + dtor(object); +} + +unsafe extern "C" fn pdo_statement_dtor(object: *mut sys::zend_object) { + debug!("call PDOStatement dtor"); + dtor(object); +} + +unsafe extern "C" fn dtor(object: *mut sys::zend_object) { + let handle = ZObj::from_ptr(object).handle(); + + DSN_MAP.remove(&handle); + if let Some((_, Some(dtor))) = DTOR_MAP.remove(&handle) { + dtor(object); + } +} + +fn after_hook( + _: Option, span: Box, execute_data: &mut ExecuteData, return_value: &mut ZVal, +) -> crate::Result<()> { + if let Some(b) = return_value.as_bool() { + if !b { + return after_hook_when_false( + get_this_mut(execute_data)?, + &mut span.downcast::().unwrap(), + ); + } + } else if let Some(obj) = return_value.as_mut_z_obj() { + if obj.get_class().get_name() == &"PDOStatement" { + return after_hook_when_pdo_statement(get_this_mut(execute_data)?, obj); + } + } + + Ok(()) +} + +fn after_hook_when_false(this: &mut ZObj, span: &mut Span) -> crate::Result<()> { + let info = this.call("errorInfo", [])?; + let info = info.as_z_arr().context("errorInfo isn't array")?; + + let state = get_error_info_item(info, 0)?.expect_z_str()?.to_str()?; + let code = { + let code = get_error_info_item(info, 1)?; + // PDOStatement::fetch + // In all cases, false is returned on failure or if there are no more rows. + if code.get_type_info().is_null() { + return Ok(()); + } + + &code.expect_long()?.to_string() + }; + let error = get_error_info_item(info, 2)?.expect_z_str()?.to_str()?; + + let mut span_object = span.span_object_mut(); + span_object.is_error = true; + span_object.add_log([("SQLSTATE", state), ("Error Code", code), ("Error", error)]); + + Ok(()) +} + +fn after_hook_when_pdo_statement(pdo: &mut ZObj, pdo_statement: &mut ZObj) -> crate::Result<()> { + let dsn = DSN_MAP + .get(&pdo.handle()) + .map(|r| r.value().clone()) + .context("DSN not found")?; + DSN_MAP.insert(pdo_statement.handle(), dsn); + hack_dtor(pdo_statement, Some(pdo_statement_dtor)); + Ok(()) +} + +fn get_error_info_item(info: &ZArr, i: u64) -> anyhow::Result<&ZVal> { + info.get(i) + .with_context(|| format!("errorInfo[{}] not exists", i)) +} + +fn create_exit_span_with_dsn( + request_id: Option, class_name: &str, function_name: &str, dsn: &Dsn, +) -> anyhow::Result { + RequestContext::try_with_global_ctx(request_id, |ctx| { + let mut span = + ctx.create_exit_span(&format!("{}->{}", class_name, function_name), &dsn.peer); + + let mut span_object = span.span_object_mut(); + span_object.set_span_layer(SpanLayer::Database); + span_object.component_id = COMPONENT_PHP_PDO_ID; + span_object.add_tag(TAG_DB_TYPE, &dsn.db_type); + span_object.add_tag("db.data_source", &dsn.data_source); + drop(span_object); + + Ok(span) + }) +} + +fn with_dsn(handle: u32, f: impl FnOnce(&Dsn) -> anyhow::Result) -> anyhow::Result { + DSN_MAP + .get(&handle) + .map(|r| f(r.value())) + .context("dns not exists")? +} + +#[derive(Debug, Clone)] +struct Dsn { + db_type: String, + data_source: String, + peer: String, +} + +impl FromStr for Dsn { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let mut ss = s.splitn(2, ':'); + let db_type = ss.next().context("unknown db type")?.to_owned(); + let data_source = ss.next().context("unknown datasource")?.to_owned(); + + let mut host = "unknown"; + let mut port = match &*db_type { + "mysql" => "3306", + "oci" => "1521", // Oracle + "sqlsrv" => "1433", + "pgsql" => "5432", + _ => "0", + }; + + let ss = data_source.split(';'); + for s in ss { + if s.is_empty() { + continue; + } + + let mut kv = s.splitn(2, '='); + let k = kv.next().context("unknown key")?; + let v = kv.next().context("unknown value")?; + + // TODO compact the fields rather than mysql. + match k { + "host" => { + host = v; + } + "port" => { + port = v; + } + _ => {} + } + } + + let peer = if host.contains(':') { + host.to_string() + } else { + host.to_string() + ":" + port + }; + + Ok(Dsn { + db_type, + data_source, + peer, + }) + } +} diff --git a/src/plugin/plugin_predis.rs b/src/plugin/plugin_predis.rs new file mode 100644 index 0000000..0b643d6 --- /dev/null +++ b/src/plugin/plugin_predis.rs @@ -0,0 +1,280 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::Plugin; +use crate::{ + component::COMPONENT_PHP_PREDIS_ID, + context::RequestContext, + execute::{get_this_mut, validate_num_args, AfterExecuteHook, BeforeExecuteHook}, + tag::{TAG_CACHE_CMD, TAG_CACHE_KEY, TAG_CACHE_OP, TAG_CACHE_TYPE}, +}; +use once_cell::sync::Lazy; +use phper::{eg, functions::call, values::ZVal}; +use skywalking::{skywalking_proto::v3::SpanLayer, trace::span::Span}; +use std::collections::HashSet; +use tracing::debug; + +pub static REDIS_READ_COMMANDS: Lazy> = Lazy::new(|| { + [ + "BLPOP", + "BRPOP", + "GET", + "GETBIT", + "GETRANGE", + "HEXISTS", + "HGET", + "HGETALL", + "HKEYS", + "HLEN", + "HMGET", + "HSCAN", + "HSTRLEN", + "HVALS", + "KEYS", + "LGET", + "LGETRANGE", + "LLEN", + "LRANGE", + "LSIZE", + "MGET", + "SCONTAINS", + "SGETMEMBERS", + "SISMEMBER", + "SMEMBERS", + "SSCAN", + "SSIZE", + "STRLEN", + "ZCOUNT", + "ZRANGE", + "ZRANGEBYLEX", + "ZRANGEBYSCORE", + "ZSCAN", + "ZSIZE", + ] + .into_iter() + .collect() +}); + +pub static REDIS_WRITE_COMMANDS: Lazy> = Lazy::new(|| { + [ + "APPEND", + "BRPOPLPUSH", + "DECR", + "DECRBY", + "DEL", + "DELETE", + "HDEL", + "HINCRBY", + "HINCRBYFLOAT", + "HMSET", + "HSET", + "HSETNX", + "INCR", + "INCRBY", + "INCRBYFLOAT", + "LINSERT", + "LPUSH", + "LPUSHX", + "LREM", + "LREMOVE", + "LSET", + "LTRIM", + "LISTTRIM", + "MSET", + "MSETNX", + "PSETEX", + "RPOPLPUSH", + "RPUSH", + "RPUSHX", + "RANDOMKEY", + "SADD", + "SINTER", + "SINTERSTORE", + "SMOVE", + "SRANDMEMBER", + "SREM", + "SREMOVE", + "SET", + "SETBIT", + "SETEX", + "SETNX", + "SETRANGE", + "SETTIMEOUT", + "SORT", + "UNLINK", + "ZADD", + "ZDELETE", + "ZDELETERANGEBYRANK", + "ZDELETERANGEBYSCORE", + "ZINCRBY", + "ZREM", + "ZREMRANGEBYRANK", + "ZREMRANGEBYSCORE", + "ZREMOVE", + "ZREMOVERANGEBYSCORE", + ] + .into_iter() + .collect() +}); + +static REDIS_OTHER_COMMANDS: Lazy> = Lazy::new(|| ["AUTH"].into_iter().collect()); + +static REDIS_ALL_COMMANDS: Lazy> = Lazy::new(|| { + let mut commands = HashSet::with_capacity( + REDIS_READ_COMMANDS.len() + REDIS_WRITE_COMMANDS.len() + REDIS_OTHER_COMMANDS.len(), + ); + commands.extend(REDIS_READ_COMMANDS.iter()); + commands.extend(REDIS_WRITE_COMMANDS.iter()); + commands.extend(REDIS_OTHER_COMMANDS.iter()); + commands +}); + +#[derive(Default, Clone)] +pub struct PredisPlugin; + +impl Plugin for PredisPlugin { + fn class_names(&self) -> Option<&'static [&'static str]> { + Some(&["Predis\\Client"]) + } + + fn function_name_prefix(&self) -> Option<&'static str> { + None + } + + fn hook( + &self, class_name: Option<&str>, function_name: &str, + ) -> Option<( + Box, + Box, + )> { + match (class_name, function_name) { + (Some(class_name @ "Predis\\Client"), function_name) + if REDIS_ALL_COMMANDS.contains(&*function_name.to_ascii_uppercase()) => + { + Some(self.hook_predis_execute_command(class_name, function_name)) + } + _ => None, + } + } +} + +enum ConnectionType { + AbstractConnection, + Unknown, +} + +impl PredisPlugin { + fn hook_predis_execute_command( + &self, class_name: &str, function_name: &str, + ) -> (Box, Box) { + let class_name = class_name.to_owned(); + let function_name = function_name.to_owned(); + ( + Box::new(move |request_id, execute_data| { + validate_num_args(execute_data, 1)?; + + let this = get_this_mut(execute_data)?; + let handle = this.handle(); + let connection = this.call("getConnection", [])?; + + let peer = Self::get_peer(connection)?; + + let cmd = function_name.to_ascii_uppercase(); + + let op = if REDIS_READ_COMMANDS.contains(&*cmd) { + Some("read") + } else if REDIS_WRITE_COMMANDS.contains(&*cmd) { + Some("write") + } else { + None + }; + + let key = op + .and_then(|_| execute_data.get_parameter(0).as_z_str()) + .and_then(|s| s.to_str().ok()); + + debug!(handle, cmd, key, op, "call redis command"); + + let mut span = RequestContext::try_with_global_ctx(request_id, |ctx| { + Ok(ctx.create_exit_span(&format!("{}->{}", class_name, function_name), &peer)) + })?; + + let mut span_object = span.span_object_mut(); + span_object.set_span_layer(SpanLayer::Cache); + span_object.component_id = COMPONENT_PHP_PREDIS_ID; + span_object.add_tag(TAG_CACHE_TYPE, "redis"); + span_object.add_tag(TAG_CACHE_CMD, cmd); + if let Some(op) = op { + span_object.add_tag(TAG_CACHE_OP, op); + } + if let Some(key) = key { + span_object.add_tag(TAG_CACHE_KEY, key) + } + drop(span_object); + + Ok(Box::new(span)) + }), + Box::new(move |_, span, _, return_value| { + let mut span = span.downcast::().unwrap(); + + let exception = unsafe { eg!(exception) }; + + debug!(?return_value, ?exception, "predis after execute command"); + + let typ = return_value.get_type_info(); + if !exception.is_null() || typ.is_false() { + span.span_object_mut().is_error = true; + } + + Ok(()) + }), + ) + } + + fn get_peer(mut connection: ZVal) -> crate::Result { + let connection_type = Self::infer_connection_type(connection.clone())?; + match connection_type { + ConnectionType::AbstractConnection => { + let connection = connection.expect_mut_z_obj()?; + + let mut parameters = connection.call("getParameters", [])?; + let parameters = parameters.expect_mut_z_obj()?; + + let host = parameters.call("__get", [ZVal::from("host")])?; + let host = host.expect_z_str()?.to_str()?; + + let port = parameters.call("__get", [ZVal::from("port")])?; + let port = port.expect_long()?; + + Ok(format!("{}:{}", host, port)) + } + ConnectionType::Unknown => Ok("unknown:0".to_owned()), + } + } + + fn infer_connection_type(connection: ZVal) -> crate::Result { + let is_abstract_connection = call( + "is_a", + [ + connection, + ZVal::from("Predis\\Connection\\AbstractConnection"), + ], + )?; + if is_abstract_connection.as_bool() == Some(true) { + return Ok(ConnectionType::AbstractConnection); + } + Ok(ConnectionType::Unknown) + } +} diff --git a/src/plugin/plugin_redis.rs b/src/plugin/plugin_redis.rs new file mode 100644 index 0000000..3db2ddf --- /dev/null +++ b/src/plugin/plugin_redis.rs @@ -0,0 +1,383 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::Plugin; +use crate::{ + component::COMPONENT_PHP_REDIS_ID, + context::RequestContext, + execute::{get_this_mut, AfterExecuteHook, BeforeExecuteHook, Noop}, + tag::{TAG_CACHE_CMD, TAG_CACHE_KEY, TAG_CACHE_OP, TAG_CACHE_TYPE}, +}; +use anyhow::Context; +use dashmap::DashMap; +use once_cell::sync::Lazy; +use phper::{ + eg, + objects::ZObj, + sys, + values::{ExecuteData, ZVal}, +}; +use skywalking::{skywalking_proto::v3::SpanLayer, trace::span::Span}; +use std::{any::Any, collections::HashMap}; +use tracing::{debug, warn}; + +static PEER_MAP: Lazy> = Lazy::new(Default::default); + +static FREE_MAP: Lazy> = Lazy::new(Default::default); + +static REDIS_READ_MAPPING: Lazy> = Lazy::new(|| { + [ + ("blpop", "BLPOP"), + ("brpop", "BRPOP"), + ("get", "GET"), + ("getbit", "GETBIT"), + ("getkeys", "KEYS"), + ("getmultiple", "MGET"), + ("getrange", "GETRANGE"), + ("hexists", "HEXISTS"), + ("hget", "HGET"), + ("hgetall", "HGETALL"), + ("hkeys", "HKEYS"), + ("hlen", "HLEN"), + ("hmget", "HMGET"), + ("hscan", "HSCAN"), + ("hstrlen", "HSTRLEN"), + ("hvals", "HVALS"), + ("keys", "KEYS"), + ("lget", "LGET"), + ("lgetrange", "LGETRANGE"), + ("llen", "LLEN"), + ("lrange", "LRANGE"), + ("lsize", "LSIZE"), + ("mget", "MGET"), + ("mget", "MGET"), + ("scontains", "SCONTAINS"), + ("sgetmembers", "SGETMEMBERS"), + ("sismember", "SISMEMBER"), + ("smembers", "SMEMBERS"), + ("sscan", "SSCAN"), + ("ssize", "SSIZE"), + ("strlen", "STRLEN"), + ("substr", "GETRANGE"), + ("zcount", "ZCOUNT"), + ("zrange", "ZRANGE"), + ("zrangebylex", "ZRANGEBYLEX"), + ("zrangebyscore", "ZRANGEBYSCORE"), + ("zscan", "ZSCAN"), + ("zsize", "ZSIZE"), + ] + .into_iter() + .collect() +}); + +static REDIS_WRITE_MAPPING: Lazy> = Lazy::new(|| { + [ + ("append", "APPEND"), + ("brpoplpush", "BRPOPLPUSH"), + ("decr", "DECR"), + ("decrby", "DECRBY"), + ("del", "DEL"), + ("delete", "DEL"), + ("hdel", "HDEL"), + ("hincrby", "HINCRBY"), + ("hincrbyfloat", "HINCRBYFLOAT"), + ("hmset", "HMSET"), + ("hset", "HSET"), + ("hsetnx", "HSETNX"), + ("incr", "INCR"), + ("incrby", "INCRBY"), + ("incrbyfloat", "INCRBYFLOAT"), + ("linsert", "LINSERT"), + ("lpush", "LPUSH"), + ("lpushx", "LPUSHX"), + ("lrem", "LREM"), + ("lremove", "LREMOVE"), + ("lset", "LSET"), + ("ltrim", "LTRIM"), + ("listtrim", "LISTTRIM"), + ("mset", "MSET"), + ("msetnx", "MSETNX"), + ("psetex", "PSETEX"), + ("rpoplpush", "RPOPLPUSH"), + ("rpush", "RPUSH"), + ("rpushx", "RPUSHX"), + ("randomkey", "RANDOMKEY"), + ("sadd", "SADD"), + ("sinter", "SINTER"), + ("sinterstore", "SINTERSTORE"), + ("smove", "SMOVE"), + ("srandmember", "SRANDMEMBER"), + ("srem", "SREM"), + ("sremove", "SREMOVE"), + ("set", "SET"), + ("setbit", "SETBIT"), + ("setex", "SETEX"), + ("setnx", "SETNX"), + ("setrange", "SETRANGE"), + ("settimeout", "SETTIMEOUT"), + ("sort", "SORT"), + ("unlink", "UNLINK"), + ("zadd", "ZADD"), + ("zdelete", "ZDELETE"), + ("zdeleterangebyrank", "ZDELETERANGEBYRANK"), + ("zdeleterangebyscore", "ZDELETERANGEBYSCORE"), + ("zincrby", "ZINCRBY"), + ("zrem", "ZREM"), + ("zremrangebyrank", "ZREMRANGEBYRANK"), + ("zremrangebyscore", "ZREMRANGEBYSCORE"), + ("zremove", "ZREMOVE"), + ("zremoverangebyscore", "ZREMOVERANGEBYSCORE"), + ] + .into_iter() + .collect() +}); + +static REDIS_OTHER_MAPPING: Lazy> = + Lazy::new(|| [("auth", "AUTH")].into_iter().collect()); + +static REDIS_ALL_MAPPING: Lazy> = Lazy::new(|| { + let mut commands = HashMap::with_capacity(REDIS_READ_MAPPING.len() + REDIS_WRITE_MAPPING.len()); + commands.extend(REDIS_READ_MAPPING.iter()); + commands.extend(REDIS_WRITE_MAPPING.iter()); + commands.extend(REDIS_OTHER_MAPPING.iter()); + commands +}); + +#[derive(Default, Clone)] +pub struct RedisPlugin; + +impl Plugin for RedisPlugin { + #[inline] + fn class_names(&self) -> Option<&'static [&'static str]> { + Some(&["Redis"]) + } + + #[inline] + fn function_name_prefix(&self) -> Option<&'static str> { + None + } + + fn hook( + &self, class_name: Option<&str>, function_name: &str, + ) -> Option<(Box, Box)> { + match (class_name, function_name) { + (Some("Redis"), "__construct") => Some(self.hook_redis_construct()), + (Some(class_name @ "Redis"), f) + if ["connect", "open", "pconnect", "popen"].contains(&f) => + { + Some(self.hook_redis_connect(class_name, function_name)) + } + (Some(class_name @ "Redis"), f) + if REDIS_ALL_MAPPING.contains_key(&*f.to_ascii_lowercase()) => + { + Some(self.hook_redis_methods(class_name, function_name)) + } + _ => None, + } + } +} + +impl RedisPlugin { + /// TODO Support first optional argument as config for phpredis 6.0+. + /// + fn hook_redis_construct(&self) -> (Box, Box) { + ( + Box::new(|_, execute_data| { + let this = get_this_mut(execute_data)?; + hack_free(this, Some(redis_dtor)); + + Ok(Box::new(())) + }), + Noop::noop(), + ) + } + + fn hook_redis_connect( + &self, class_name: &str, function_name: &str, + ) -> (Box, Box) { + let class_name = class_name.to_owned(); + let function_name = function_name.to_owned(); + ( + Box::new(move |request_id, execute_data| { + if execute_data.num_args() < 2 { + debug!("argument count less than 2, skipped."); + return Ok(Box::new(())); + } + + let host = { + let f = || { + Ok::<_, anyhow::Error>( + execute_data + .get_parameter(0) + .as_z_str() + .context("isn't string")? + .to_str()? + .to_owned(), + ) + }; + match f() { + Ok(host) => host, + Err(err) => { + warn!(?err, "parse first argument to host failed, skipped."); + return Ok(Box::new(())); + } + } + }; + let port = { + let f = || { + execute_data + .get_parameter(1) + .as_long() + .context("isn't long") + }; + match f() { + Ok(port) => port, + Err(err) => { + warn!(?err, "parse second argument to port failed, skipped."); + return Ok(Box::new(())); + } + } + }; + + let this = get_this_mut(execute_data)?; + let addr = format!("{}:{}", host, port); + debug!(addr, "Get redis peer"); + PEER_MAP.insert(this.handle(), Peer { addr: addr.clone() }); + + let mut span = RequestContext::try_with_global_ctx(request_id, |ctx| { + Ok(ctx.create_exit_span(&format!("{}->{}", class_name, function_name), &addr)) + })?; + + let mut span_object = span.span_object_mut(); + span_object.set_span_layer(SpanLayer::Cache); + span_object.component_id = COMPONENT_PHP_REDIS_ID; + span_object.add_tag(TAG_CACHE_TYPE, "redis"); + drop(span_object); + + Ok(Box::new(span)) + }), + Box::new(after_hook), + ) + } + + fn hook_redis_methods( + &self, class_name: &str, function_name: &str, + ) -> (Box, Box) { + let class_name = class_name.to_owned(); + let function_name = function_name.to_owned(); + ( + Box::new(move |request_id, execute_data| { + let handle = get_this_mut(execute_data)?.handle(); + debug!(handle, function_name, "call redis method"); + let peer = PEER_MAP + .get(&handle) + .map(|r| r.value().addr.clone()) + .unwrap_or_default(); + + let function_name_key = &*function_name.to_ascii_lowercase(); + + let op = if REDIS_READ_MAPPING.contains_key(function_name_key) { + Some("read") + } else if REDIS_WRITE_MAPPING.contains_key(function_name_key) { + Some("write") + } else { + None + }; + + let key = op + .and_then(|_| execute_data.get_parameter(0).as_z_str()) + .and_then(|s| s.to_str().ok()); + + debug!(handle, cmd = function_name, key, op, "call redis command"); + + let mut span = RequestContext::try_with_global_ctx(request_id, |ctx| { + Ok(ctx.create_exit_span(&format!("{}->{}", class_name, function_name), &peer)) + })?; + + let mut span_object = span.span_object_mut(); + span_object.set_span_layer(SpanLayer::Cache); + span_object.component_id = COMPONENT_PHP_REDIS_ID; + span_object.add_tag(TAG_CACHE_TYPE, "redis"); + span_object.add_tag( + TAG_CACHE_CMD, + *REDIS_ALL_MAPPING.get(function_name_key).unwrap(), + ); + if let Some(op) = op { + span_object.add_tag(TAG_CACHE_OP, op); + } + if let Some(key) = key { + span_object.add_tag(TAG_CACHE_KEY, key) + } + drop(span_object); + + Ok(Box::new(span)) + }), + Box::new(after_hook), + ) + } +} + +struct Peer { + addr: String, +} + +fn hack_free(this: &mut ZObj, new_free: sys::zend_object_free_obj_t) { + let handle = this.handle(); + + unsafe { + let ori_free = (*(*this.as_mut_ptr()).handlers).free_obj; + FREE_MAP.insert(handle, ori_free); + (*((*this.as_mut_ptr()).handlers as *mut sys::zend_object_handlers)).free_obj = new_free; + } +} + +unsafe extern "C" fn redis_dtor(object: *mut sys::zend_object) { + debug!("call Redis free"); + + let handle = ZObj::from_ptr(object).handle(); + + PEER_MAP.remove(&handle); + if let Some((_, Some(free))) = FREE_MAP.remove(&handle) { + free(object); + } +} + +fn after_hook( + _request_id: Option, span: Box, _execute_data: &mut ExecuteData, + _return_value: &mut ZVal, +) -> crate::Result<()> { + let mut span = span.downcast::().unwrap(); + + let ex = unsafe { ZObj::try_from_mut_ptr(eg!(exception)) }; + if let Some(ex) = ex { + let mut span_object = span.span_object_mut(); + span_object.is_error = true; + + let mut logs = Vec::new(); + if let Ok(class_name) = ex.get_class().get_name().to_str() { + logs.push(("Exception Class", class_name.to_owned())); + } + if let Some(message) = ex.get_property("message").as_z_str() { + if let Ok(message) = message.to_str() { + logs.push(("Exception Message", message.to_owned())); + } + } + if !logs.is_empty() { + span_object.add_log(logs); + } + } + + Ok(()) +} diff --git a/src/plugin/plugin_swoole.rs b/src/plugin/plugin_swoole.rs new file mode 100644 index 0000000..d405388 --- /dev/null +++ b/src/plugin/plugin_swoole.rs @@ -0,0 +1,136 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{ + execute::{get_this_mut, validate_num_args, AfterExecuteHook, BeforeExecuteHook, Noop}, + plugin::Plugin, + request::{ + HACK_SWOOLE_ON_REQUEST_FUNCTION_NAME, IS_SWOOLE, ORI_SWOOLE_ON_REQUEST, + SWOOLE_RESPONSE_STATUS_MAP, + }, +}; +use phper::{strings::ZString, values::ZVal}; +use std::{mem::replace, sync::atomic::Ordering}; + +#[derive(Default, Clone)] +pub struct SwooleServerPlugin; + +impl Plugin for SwooleServerPlugin { + #[inline] + fn class_names(&self) -> Option<&'static [&'static str]> { + Some(&["Swoole\\Server"]) + } + + #[inline] + fn function_name_prefix(&self) -> Option<&'static str> { + None + } + + fn hook( + &self, _class_name: Option<&str>, function_name: &str, + ) -> Option<(Box, Box)> { + match function_name { + "on" => Some(self.hook_on()), + _ => None, + } + } +} + +impl SwooleServerPlugin { + fn hook_on(&self) -> (Box, Box) { + ( + Box::new(|_, execute_data| { + validate_num_args(execute_data, 2)?; + + let on = execute_data.get_parameter(0); + if !on.as_z_str().map(|s| s == b"request").unwrap_or_default() { + return Ok(Box::new(())); + } + + // Hack the closure with the + // [`crate::request::skywalking_hack_swoole_on_request`]. + let closure = execute_data.get_mut_parameter(1); + let ori_closure = replace( + closure, + ZVal::from(ZString::new(HACK_SWOOLE_ON_REQUEST_FUNCTION_NAME)), + ); + + ORI_SWOOLE_ON_REQUEST.store( + Box::into_raw(Box::new(ori_closure)).cast(), + Ordering::Relaxed, + ); + IS_SWOOLE.store(true, Ordering::Relaxed); + + Ok(Box::new(())) + }), + Noop::noop(), + ) + } +} + +#[derive(Default, Clone)] +pub struct SwooleHttpResponsePlugin; + +impl Plugin for SwooleHttpResponsePlugin { + #[inline] + fn class_names(&self) -> Option<&'static [&'static str]> { + Some(&["Swoole\\Http\\Response"]) + } + + #[inline] + fn function_name_prefix(&self) -> Option<&'static str> { + None + } + + fn hook( + &self, _class_name: Option<&str>, function_name: &str, + ) -> Option<(Box, Box)> { + match function_name { + "status" => Some(self.hook_status()), + _ => None, + } + } +} + +impl SwooleHttpResponsePlugin { + fn hook_status(&self) -> (Box, Box) { + ( + Box::new(|_, execute_data| { + validate_num_args(execute_data, 1)?; + + let fd = get_this_mut(execute_data)? + .get_mut_property("fd") + .expect_long()?; + + let status = execute_data.get_parameter(0); + let status = status + .as_long() + .map(|status| status as i32) + .or_else(|| { + status + .as_z_str() + .and_then(|status| status.to_str().ok()) + .and_then(|status| status.parse::().ok()) + }) + .unwrap_or_default(); + + SWOOLE_RESPONSE_STATUS_MAP.insert(fd, status); + + Ok(Box::new(())) + }), + Noop::noop(), + ) + } +} diff --git a/src/request.rs b/src/request.rs new file mode 100644 index 0000000..160164f --- /dev/null +++ b/src/request.rs @@ -0,0 +1,333 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{component::COMPONENT_PHP_ID, context::RequestContext, module::{is_enable, SKYWALKING_VERSION}, util::{catch_unwind_result, get_sapi_module_name, z_val_to_string}}; +use anyhow::{anyhow, Context}; +use dashmap::DashMap; +use once_cell::sync::Lazy; +use phper::{arrays::ZArr, eg, pg, sg, sys, values::ZVal}; +use skywalking::trace::{propagation::decoder::decode_propagation, tracer}; +use std::{ + panic::AssertUnwindSafe, + ptr::null_mut, + sync::atomic::{AtomicBool, AtomicPtr, Ordering}, +}; +use phper::functions::call; +use tracing::{error, instrument, trace, warn}; +use url::Url; + +#[instrument(skip_all)] +pub fn init() { + if !is_enable() { + return; + } + if get_sapi_module_name().to_bytes() == b"fpm-fcgi" { + if let Err(err) = catch_unwind_result(request_init_for_fpm) { + error!(mode = "fpm", ?err, "request init failed"); + } + } +} + +#[instrument(skip_all)] +pub fn shutdown() { + if !is_enable() { + return; + } + if get_sapi_module_name().to_bytes() == b"fpm-fcgi" { + if let Err(err) = catch_unwind_result(request_shutdown_for_fpm) { + error!(mode = "fpm", ?err, "request shutdown failed"); + } + } +} + +fn request_init_for_fpm() -> crate::Result<()> { + jit_initialization(); + + let server = get_page_request_server()?; + + let header = get_page_request_header(server); + let url = get_page_request_url(server)?; + let method = get_page_request_method(server); + create_request_context(None, header.as_deref(), &method, &url) +} + +fn request_shutdown_for_fpm() -> crate::Result<()> { + let status_code = unsafe { sg!(sapi_headers).http_response_code }; + finish_request_context(None, status_code) +} + +#[allow(clippy::useless_conversion)] +fn jit_initialization() { + unsafe { + let jit_initialization: u8 = pg!(auto_globals_jit).into(); + if jit_initialization != 0 { + let mut server = "_SERVER".to_string(); + sys::zend_is_auto_global_str(server.as_mut_ptr().cast(), server.len()); + } + } +} + +fn get_page_request_header(server: &ZArr) -> Option { + if *SKYWALKING_VERSION >= 8 { + server + .get("HTTP_SW8") + .and_then(|sw| sw.as_z_str()) + .and_then(|zs| zs.to_str().ok()) + .map(|s| s.to_string()) + } else { + None + } +} + +fn get_page_request_url(server: &ZArr) -> crate::Result { + let scheme = if [Some("1"), Some("on")] + .contains(&server.get("HTTPS").and_then(z_val_to_string).as_deref()) + { + "https" + } else { + "http" + }; + + let addr = server + .get("HTTP_HOST") + .and_then(z_val_to_string) + .or_else(|| { + server + .get("SERVER_PORT") + .and_then(z_val_to_string) + .map(|port| format!("localhost:{}", port)) + }) + .unwrap_or_else(|| "unknown:0".to_string()); + + let uri = server + .get("REQUEST_URI") + .and_then(z_val_to_string) + .or_else(|| server.get("PHP_SELF").and_then(z_val_to_string)) + .or_else(|| server.get("SCRIPT_NAME").and_then(z_val_to_string)) + .unwrap_or_else(|| "/unknown".to_string()); + + Ok(Url::parse(&format!("{}://{}{}", scheme, addr, uri))?) +} + +fn get_page_request_method(server: &ZArr) -> String { + server + .get("REQUEST_METHOD") + .and_then(z_val_to_string) + .unwrap_or_else(|| "UNKNOWN".to_string()) +} + +fn get_page_request_server<'a>() -> anyhow::Result<&'a ZArr> { + unsafe { + let symbol_table = ZArr::from_mut_ptr(&mut eg!(symbol_table)); + let carrier = symbol_table + .get("_SERVER") + .and_then(|carrier| carrier.as_z_arr()) + .context("$_SERVER is null")?; + Ok(carrier) + } +} + +pub const HACK_SWOOLE_ON_REQUEST_FUNCTION_NAME: &str = + "skywalking_hack_swoole_on_request_please_do_not_use"; + +/// Hold the response fd and status code kvs, because I dont't found that +/// response has the status field, so I hook the response.status method, maybe +/// there is a better way? +pub static SWOOLE_RESPONSE_STATUS_MAP: Lazy> = Lazy::new(DashMap::new); + +pub static ORI_SWOOLE_ON_REQUEST: AtomicPtr = AtomicPtr::new(null_mut()); + +pub static IS_SWOOLE: AtomicBool = AtomicBool::new(false); + +/// The function is used by swoole plugin, to surround the callback of on +/// request. +pub fn skywalking_hack_swoole_on_request(args: &mut [ZVal]) -> phper::Result { + let f = ORI_SWOOLE_ON_REQUEST.load(Ordering::Relaxed); + if f.is_null() { + error!("Origin swoole on request handler is null"); + return Ok(ZVal::from(())); + } + let f = unsafe { ZVal::from_mut_ptr(f) }; + + let result = catch_unwind_result(AssertUnwindSafe(|| request_init_for_swoole(&mut args[0]))); + if let Err(err) = &result { + error!(mode = "swoole", ?err, "request init failed"); + } + + let return_value = f.call(&mut *args); + if let Err(err) = &return_value { + error!( + mode = "swoole", + ?err, + "Something wrong when call the origin on-request handler" + ); + } + + if result.is_ok() { + if let Err(err) = catch_unwind_result(AssertUnwindSafe(move || { + request_shutdown_for_swoole(&mut args[1]) + })) { + error!(mode = "swoole", ?err, "request shutdown failed"); + } + } + + return_value +} + +fn request_init_for_swoole(request: &mut ZVal) -> crate::Result<()> { + let request = request.as_z_obj().context("swoole request isn't object")?; + + let fd = request + .get_property("fd") + .as_long() + .context("swoole request fd not exists")?; + + let headers = request + .get_property("header") + .as_z_arr() + .context("swoole request header not exists")?; + + let header = get_swoole_request_header(headers); + + let server = request + .get_property("server") + .as_z_arr() + .context("swoole request server not exists")?; + + let method = get_swoole_request_method(server); + let url = get_swoole_request_url(server, headers)?; + + create_request_context(Some(fd), header.as_deref(), &method, &url) +} + +fn request_shutdown_for_swoole(response: &mut ZVal) -> crate::Result<()> { + let response = response + .as_mut_z_obj() + .context("swoole response isn't object")?; + + let fd = response + .get_mut_property("fd") + .as_long() + .context("swoole request fd not exists")?; + + finish_request_context( + Some(fd), + SWOOLE_RESPONSE_STATUS_MAP + .remove(&fd) + .map(|(_, status)| status) + .unwrap_or(200), + ) +} + +fn get_swoole_request_header(header: &ZArr) -> Option { + if *SKYWALKING_VERSION >= 8 { + header + .get("sw8") + .and_then(|sw| sw.as_z_str()) + .and_then(|zs| zs.to_str().ok()) + .map(|s| s.to_string()) + } else { + None + } +} + +fn get_swoole_request_url(server: &ZArr, headers: &ZArr) -> crate::Result { + let addr = headers + .get("host") + .and_then(z_val_to_string) + .or_else(|| { + server + .get("server_port") + .and_then(z_val_to_string) + .map(|port| format!("localhost:{}", port)) + }) + .unwrap_or_else(|| "unknown:0".to_string()); + + let uri = server + .get("request_uri") + .and_then(z_val_to_string) + .unwrap_or_else(|| "/unknown".to_string()); + + let query = server + .get("query_string") + .and_then(z_val_to_string) + .map(|s| format!("?{}", s)) + .unwrap_or_default(); + + Ok(Url::parse(&format!("http://{}{}{}", addr, uri, query))?) +} + +fn get_swoole_request_method(server: &ZArr) -> String { + server + .get("request_method") + .and_then(z_val_to_string) + .unwrap_or_else(|| "UNKNOWN".to_string()) +} + +fn create_request_context( + request_id: Option, header: Option<&str>, method: &str, url: &Url, +) -> crate::Result<()> { + let propagation = header + .map(decode_propagation) + .transpose() + .map_err(|e| anyhow!("decode propagation failed: {}", e))?; + + trace!("Propagation: {:?}", &propagation); + + let mut ctx = tracer::create_trace_context(); + let c_ctx = ctx.trace_id(); + // 定义一个PHP常量,常量值等于 skywalking 的 trace_id + call("define", [ZVal::from("SW_TRACE_ID"), ZVal::from(c_ctx)]).expect("define SW_TRACE_ID error"); + + let operation_name = format!("{}:{}", method, url.path()); + let mut span = match propagation { + Some(propagation) => ctx.create_entry_span_with_propagation(&operation_name, &propagation), + None => ctx.create_entry_span(&operation_name), + }; + + let mut span_object = span.span_object_mut(); + span_object.component_id = COMPONENT_PHP_ID; + span_object.add_tag("url", url.to_string()); + span_object.add_tag("http.method", method); + drop(span_object); + + let rx = RequestContext { + tracing_context: ctx, + entry_span: span, + }; + RequestContext::set_global( + request_id, + rx, + ); + + Ok(()) +} + +fn finish_request_context(request_id: Option, status_code: i32) -> crate::Result<()> { + let RequestContext { + tracing_context, + mut entry_span, + } = RequestContext::remove_global(request_id).context("request context not exists")?; + + entry_span.add_tag("http.status_code", &status_code.to_string()); + if status_code >= 400 { + entry_span.span_object_mut().is_error = true; + } + + drop(entry_span); + drop(tracing_context); + + Ok(()) +} diff --git a/src/tag.rs b/src/tag.rs new file mode 100644 index 0000000..c408390 --- /dev/null +++ b/src/tag.rs @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License.. + +//! Tags +//! +//! Virtual Cache +//! +//! https://skywalking.apache.org/docs/main/next/en/setup/service-agent/virtual-cache/ +//! +//! Virtual Database +//! +//! https://skywalking.apache.org/docs/main/next/en/setup/service-agent/virtual-database/ + +use std::fmt::Display; + +pub const TAG_CACHE_TYPE: &str = "cache.type"; +pub const TAG_CACHE_OP: &str = "cache.op"; +pub const TAG_CACHE_CMD: &str = "cache.cmd"; +pub const TAG_CACHE_KEY: &str = "cache.key"; + +pub enum CacheOp { + Read, + Write, +} + +impl Display for CacheOp { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Read => write!(f, "read"), + Self::Write => write!(f, "write"), + } + } +} + +pub const TAG_DB_STATEMENT: &str = "db.statement"; +pub const TAG_DB_TYPE: &str = "db.type"; + +pub const TAG_MQ_BROKER: &str = "mq.broker"; +pub const TAG_MQ_TOPIC: &str = "mq.topic"; +pub const TAG_MQ_QUEUE: &str = "mq.queue"; diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..7dd575c --- /dev/null +++ b/src/util.rs @@ -0,0 +1,98 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use anyhow::anyhow; +use once_cell::sync::Lazy; +use phper::{sys, values::ZVal}; +use std::{ + ffi::CStr, + os::unix::prelude::OsStrExt, + panic::{catch_unwind, UnwindSafe}, + path::Path, +}; +use systemstat::{IpAddr, Platform, System}; + +pub static IPS: Lazy> = Lazy::new(|| { + System::new() + .networks() + .ok() + .and_then(|networks| { + let addrs = networks + .values() + .flat_map(|network| { + network + .addrs + .iter() + .filter_map(|network_addr| match network_addr.addr { + IpAddr::V4(addr) => { + if network.name == "lo" + || network.name.starts_with("docker") + || network.name.starts_with("br-") + { + None + } else { + Some(addr.to_string()) + } + } + _ => None, + }) + }) + .collect::>(); + + if addrs.is_empty() { + None + } else { + Some(addrs) + } + }) + .unwrap_or_else(|| vec!["127.0.0.1".to_owned()]) +}); + +pub fn z_val_to_string(zv: &ZVal) -> Option { + zv.as_z_str() + .and_then(|zs| zs.to_str().ok()) + .map(|s| s.to_string()) +} + +pub fn catch_unwind_result crate::Result + UnwindSafe, R>( + f: F, +) -> crate::Result { + match catch_unwind(f) { + Ok(r) => r, + Err(e) => { + if let Some(s) = e.downcast_ref::<&str>() { + Err(anyhow!("paniced: {}", s).into()) + } else if let Some(s) = e.downcast_ref::() { + Err(anyhow!("paniced: {}", s).into()) + } else { + Err(anyhow!("paniced").into()) + } + } + } +} + +pub fn get_sapi_module_name() -> &'static CStr { + unsafe { CStr::from_ptr(sys::sapi_module.name) } +} + +pub fn change_permission(f: impl AsRef, mode: libc::mode_t) { + let f = f.as_ref().as_os_str().as_bytes(); + let mut path = Vec::with_capacity(f.len() + 1); + path.extend_from_slice(f); + path.push(b'\0'); + unsafe { + libc::chmod(path.as_ptr().cast(), mode); + } +} diff --git a/src/worker.rs b/src/worker.rs new file mode 100644 index 0000000..19210db --- /dev/null +++ b/src/worker.rs @@ -0,0 +1,318 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{ + channel::{self, TxReporter}, + module::{ + AUTHENTICATION, ENABLE_TLS, HEARTBEAT_PERIOD, PROPERTIES_REPORT_PERIOD_FACTOR, + SERVICE_INSTANCE, SERVICE_NAME, SOCKET_FILE_PATH, SSL_CERT_CHAIN_PATH, SSL_KEY_PATH, + SSL_TRUSTED_CA_PATH, + }, + util::change_permission, + SKYWALKING_AGENT_SERVER_ADDR, SKYWALKING_AGENT_WORKER_THREADS, +}; +use anyhow::anyhow; +use once_cell::sync::Lazy; +use phper::ini::ini_get; +use skywalking::{ + management::{instance::Properties, manager::Manager}, + reporter::{ + grpc::{CollectItemConsume, GrpcReporter}, + CollectItem, + }, +}; +use std::{ + cmp::Ordering, error::Error, ffi::CStr, fs, io, marker::PhantomData, num::NonZeroUsize, + process::exit, thread::available_parallelism, time::Duration, +}; +use tokio::{ + net::UnixListener, + runtime::{self, Runtime}, + select, + signal::unix::{signal, SignalKind}, + sync::mpsc::{self, error::TrySendError}, + time::sleep, +}; +use tonic::{ + async_trait, + transport::{Certificate, Channel, ClientTlsConfig, Endpoint, Identity}, +}; +use tracing::{debug, error, info, warn}; + +pub fn init_worker() { + let server_addr = ini_get::>(SKYWALKING_AGENT_SERVER_ADDR) + .and_then(|s| s.to_str().ok()) + .unwrap_or_default() + .to_owned(); + let worker_threads = worker_threads(); + + unsafe { + // TODO Shutdown previous worker before fork if there is a PHP-FPM reload + // operation. + // TODO Change the worker process name. + + let pid = libc::fork(); + match pid.cmp(&0) { + Ordering::Less => { + error!("fork failed"); + } + Ordering::Equal => { + // Ensure worker process exits when master process exists. + #[cfg(target_os = "linux")] + libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGTERM); + + // Run the worker in subprocess. + let rt = new_tokio_runtime(worker_threads); + match rt.block_on(start_worker(server_addr)) { + Ok(_) => { + exit(0); + } + Err(err) => { + error!(?err, "worker exit unexpectedly"); + exit(1); + } + } + } + Ordering::Greater => {} + } + } +} + +fn worker_threads() -> usize { + let worker_threads = ini_get::(SKYWALKING_AGENT_WORKER_THREADS); + if worker_threads <= 0 { + available_parallelism().map(NonZeroUsize::get).unwrap_or(1) + } else { + worker_threads as usize + } +} + +fn new_tokio_runtime(worker_threads: usize) -> Runtime { + runtime::Builder::new_multi_thread() + .thread_name("sw: worker") + .enable_all() + .worker_threads(worker_threads) + .build() + .unwrap() +} + +async fn start_worker(server_addr: String) -> anyhow::Result<()> { + debug!("Starting worker..."); + + // Ensure to cleanup resources when worker exits. + let _guard = WorkerExitGuard::default(); + + // Graceful shutdown signal, put it on the top of program. + let mut sig_term = signal(SignalKind::terminate())?; + let mut sig_int = signal(SignalKind::interrupt())?; + + let socket_file = &*SOCKET_FILE_PATH; + + let fut = async move { + debug!(?socket_file, "Bind unix stream"); + let listener = UnixListener::bind(socket_file)?; + change_permission(socket_file, 0o777); + + let (tx, rx) = mpsc::channel::(255); + let tx_ = tx.clone(); + tokio::spawn(async move { + loop { + match listener.accept().await { + Ok((mut stream, _addr)) => { + let tx = tx.clone(); + + tokio::spawn(async move { + debug!("Entering channel_receive loop"); + + loop { + let r = match channel::channel_receive(&mut stream).await { + Err(err) => match err.downcast_ref::() { + Some(e) if e.kind() == io::ErrorKind::UnexpectedEof => { + debug!("Leaving channel_receive loop"); + return; + } + _ => { + error!(?err, "channel_receive failed"); + continue; + } + }, + Ok(i) => i, + }; + + // Try send here, to prevent the ipc blocking caused by the channel + // bursting (too late to report), + // which affects the pool process of php-fpm. + if let Err(err) = tx.try_send(r) { + error!(?err, "Send collect item failed"); + if !matches!(err, TrySendError::Full(_)) { + return; + } + } + } + }); + } + Err(err) => { + error!(?err, "Accept failed"); + } + } + } + }); + + let endpoint = create_endpoint(&server_addr).await?; + let channel = connect(endpoint).await; + + report_properties_and_keep_alive(TxReporter(tx_)); + + let mut reporter = GrpcReporter::new_with_pc(channel, (), Consumer(rx)); + + if !AUTHENTICATION.is_empty() { + reporter = reporter.with_authentication(&*AUTHENTICATION); + } + + info!("Worker is ready..."); + + let handle = reporter + .reporting() + .await + .with_status_handle(|message, status| { + warn!(?status, "Collect failed: {}", message); + }) + .spawn(); + + handle + .await + .map_err(|err| anyhow!("Tracer reporting failed: {:?}", err))?; + + Ok::<_, anyhow::Error>(()) + }; + + // TODO Do graceful shutdown, and wait 10s then force quit. + select! { + _ = sig_term.recv() => {} + _ = sig_int.recv() => {} + r = fut => { + r?; + } + } + + info!("Start to shutdown skywalking grpc reporter"); + + Ok(()) +} + +async fn create_endpoint(server_addr: &str) -> anyhow::Result { + let scheme = if *ENABLE_TLS { "https" } else { "http" }; + + let url = format!("{}://{}", scheme, server_addr); + debug!(url, "Create Endpoint"); + let mut endpoint = Endpoint::from_shared(url)?; + + if *ENABLE_TLS { + let domain_name = server_addr.split(':').next().unwrap_or_default(); + debug!(domain_name, "Configure TLS domain"); + let mut tls = ClientTlsConfig::new().domain_name(domain_name); + + let ssl_trusted_ca_path = SSL_TRUSTED_CA_PATH.as_str(); + if !ssl_trusted_ca_path.is_empty() { + debug!(ssl_trusted_ca_path, "Configure TLS CA"); + let ca_cert = tokio::fs::read(&*SSL_TRUSTED_CA_PATH).await?; + let ca_cert = Certificate::from_pem(ca_cert); + tls = tls.ca_certificate(ca_cert); + } + + let ssl_key_path = SSL_KEY_PATH.as_str(); + let ssl_cert_chain_path = SSL_CERT_CHAIN_PATH.as_str(); + if !ssl_key_path.is_empty() && !ssl_cert_chain_path.is_empty() { + debug!(ssl_trusted_ca_path, "Configure mTLS"); + let client_cert = tokio::fs::read(&*SSL_CERT_CHAIN_PATH).await?; + let client_key = tokio::fs::read(&*SSL_KEY_PATH).await?; + let client_identity = Identity::from_pem(client_cert, client_key); + tls = tls.identity(client_identity); + } + + endpoint = endpoint.tls_config(tls)?; + } + + Ok(endpoint) +} + +#[tracing::instrument(skip_all)] +async fn connect(endpoint: Endpoint) -> Channel { + let channel = loop { + match endpoint.connect().await { + Ok(channel) => break channel, + Err(err) => { + warn!(?err, "Connect to skywalking server failed, retry after 10s"); + sleep(Duration::from_secs(10)).await; + } + } + }; + + let uri = &*endpoint.uri().to_string(); + info!(uri, "Skywalking server connected"); + + channel +} + +struct Consumer(mpsc::Receiver); + +#[async_trait] +impl CollectItemConsume for Consumer { + async fn consume(&mut self) -> Result, Box> { + Ok(self.0.recv().await) + } + + async fn try_consume(&mut self) -> Result, Box> { + Ok(self.0.try_recv().ok()) + } +} + +#[derive(Default)] +struct WorkerExitGuard(PhantomData<()>); + +impl Drop for WorkerExitGuard { + fn drop(&mut self) { + match Lazy::get(&SOCKET_FILE_PATH) { + Some(socket_file) => { + info!(?socket_file, "Remove socket file"); + if let Err(err) = fs::remove_file(socket_file) { + error!(?err, "Remove socket file failed"); + } + } + None => { + warn!("Socket file not created"); + } + } + } +} + +fn report_properties_and_keep_alive(reporter: TxReporter) { + let manager = Manager::new(&*SERVICE_NAME, &*SERVICE_INSTANCE, reporter); + + manager.report_and_keep_alive( + || { + let mut props = Properties::new(); + props.insert_os_info(); + props.update(Properties::KEY_LANGUAGE, "php"); + props.update(Properties::KEY_PROCESS_NO, unsafe { + libc::getppid().to_string() + }); + debug!(?props, "Report instance properties"); + props + }, + Duration::from_secs(*HEARTBEAT_PERIOD as u64), + *PROPERTIES_REPORT_PERIOD_FACTOR as usize, + ); +} diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 0000000..91dbee1 --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1,358 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use anyhow::{bail, Context}; +use axum::{ + body::Body, + extract::ConnectInfo, + http::{Request, StatusCode}, + response::IntoResponse, + routing::any, + Extension, Router, +}; +use futures_util::future::join_all; +use libc::{kill, pid_t, SIGTERM}; +use once_cell::sync::Lazy; +use std::{ + env, + fs::File, + io::{self, Cursor}, + net::SocketAddr, + process::{ExitStatus, Stdio}, + sync::Arc, + thread, + time::Duration, +}; +use tokio::{ + net::TcpStream, + process::{Child, Command}, + task::JoinHandle, +}; +use tokio_stream::StreamExt; +use tracing::{error, info, instrument, Level}; +use tracing_subscriber::FmtSubscriber; + +pub const PROCESS_LOG_LEVEL: &str = "DEBUG"; + +pub const PROXY_SERVER_1_ADDRESS: &str = "127.0.0.1:9011"; +pub const PROXY_SERVER_2_ADDRESS: &str = "127.0.0.1:9012"; +pub const FPM_SERVER_1_ADDRESS: &str = "127.0.0.1:9001"; +pub const FPM_SERVER_2_ADDRESS: &str = "127.0.0.1:9002"; +pub const SWOOLE_SERVER_1_ADDRESS: &str = "127.0.0.1:9501"; +pub const SWOOLE_SERVER_2_ADDRESS: &str = "127.0.0.1:9502"; +pub const COLLECTOR_GRPC_ADDRESS: &str = "127.0.0.1:19876"; +pub const COLLECTOR_HTTP_ADDRESS: &str = "127.0.0.1:12800"; + +pub const TARGET: &str = if cfg!(debug_assertions) { + "debug" +} else { + "release" +}; + +pub const EXT: &str = if cfg!(target_os = "linux") { + ".so" +} else if cfg!(target_os = "macos") { + ".dylib" +} else { + "" +}; + +pub static HTTP_CLIENT: Lazy = Lazy::new(reqwest::Client::new); + +pub struct Fixture { + http_server_1_handle: JoinHandle<()>, + http_server_2_handle: JoinHandle<()>, + php_fpm_1_child: Child, + php_fpm_2_child: Child, + php_swoole_1_child: Child, + php_swoole_2_child: Child, +} + +pub async fn setup() -> Fixture { + setup_logging(); + Fixture { + http_server_1_handle: tokio::spawn(setup_http_proxy_server( + PROXY_SERVER_1_ADDRESS, + FPM_SERVER_1_ADDRESS, + )), + http_server_2_handle: tokio::spawn(setup_http_proxy_server( + PROXY_SERVER_2_ADDRESS, + FPM_SERVER_2_ADDRESS, + )), + php_fpm_1_child: setup_php_fpm(1, FPM_SERVER_1_ADDRESS), + php_fpm_2_child: setup_php_fpm(2, FPM_SERVER_2_ADDRESS), + php_swoole_1_child: setup_php_swoole(1), + php_swoole_2_child: setup_php_swoole(2), + } +} + +pub async fn teardown(fixture: Fixture) { + fixture.http_server_1_handle.abort(); + fixture.http_server_2_handle.abort(); + + let results = join_all([ + kill_command(fixture.php_fpm_1_child), + kill_command(fixture.php_fpm_2_child), + kill_command(fixture.php_swoole_1_child), + kill_command(fixture.php_swoole_2_child), + ]) + .await; + for result in results { + assert!(result.unwrap().success()); + } +} + +fn setup_logging() { + let subscriber = FmtSubscriber::builder() + .with_max_level(Level::INFO) + .finish(); + + tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed"); +} + +#[derive(Debug)] +struct State { + http_addr: SocketAddr, + fpm_addr: SocketAddr, +} + +#[instrument] +async fn setup_http_proxy_server(http_addr: &str, fpm_addr: &'static str) { + let http_addr = http_addr.parse().unwrap(); + let fpm_addr = fpm_addr.parse().unwrap(); + let state = Arc::new(State { + http_addr, + fpm_addr, + }); + info!(?state, "start http proxy server"); + + let app = Router::new() + .route("/*path", any(http_proxy_fpm_handler)) + .layer(Extension(state.clone())); + axum::Server::bind(&state.http_addr) + .serve(app.into_make_service_with_connect_info::()) + .await + .unwrap(); +} + +#[instrument(skip_all)] +async fn http_proxy_fpm_handler( + ConnectInfo(remote_addr): ConnectInfo, Extension(state): Extension>, + mut req: Request, +) -> impl IntoResponse { + let fut = async move { + let method = &req.method().to_string(); + let path = &req.uri().path().to_string(); + let query = &req.uri().query().unwrap_or_default().to_string(); + + let stream = TcpStream::connect(&state.fpm_addr).await?; + let client = fastcgi_client::Client::new(stream); + + let mut params = fastcgi_client::Params::default() + .request_method(method) + .query_string(&*query) + .server_addr(state.http_addr.ip().to_string()) + .server_port(state.http_addr.port()) + .remote_addr(remote_addr.ip().to_string()) + .remote_port(remote_addr.port()) + .server_name("TEST"); + + // Only tread with skywalking and custom headers. + for (key, value) in req.headers() { + let mut param_key = String::new(); + + if key.as_str().starts_with("content-") { + param_key = key.as_str().replace('-', "_").to_uppercase(); + } else if key.as_str().starts_with("sw") + || key.as_str().starts_with("x-") + || key.as_str() == "host" + { + param_key = "HTTP_".to_owned() + &key.as_str().replace('-', "_").to_uppercase(); + } + + if !param_key.is_empty() { + params.insert( + param_key.into(), + std::str::from_utf8(value.as_bytes())?.to_string().into(), + ); + } + } + + let mut buffer = Vec::new(); + while let Some(buf) = req.body_mut().next().await { + let buf = buf.context("read body failed")?; + buffer.extend_from_slice(&buf); + } + + let params = params_set_script(params, &path, &query); + + info!(?params, "proxy http to php-fpm"); + + let fastcgi_client::Response { stdout, stderr, .. } = client + .execute_once(fastcgi_client::Request::new(params, Cursor::new(buffer))) + .await + .context("request fpm failed")?; + + if let Some(stderr) = stderr { + return Ok(( + StatusCode::INTERNAL_SERVER_ERROR, + String::from_utf8(stderr).context("decode to UTF-8 string failed")?, + )); + } + + // Without tread with headers, because it is just for tests. + if let Some(stdout) = stdout { + let mut content = String::from_utf8(stdout)?; + if let Some(index) = content.find("\r\n\r\n") { + content.replace_range(..index + 4, ""); + } + return Ok((StatusCode::OK, content)); + } + + bail!("stdout and stderr are empty"); + }; + match fut.await { + Ok(x) => x, + Err(err) => { + error!(?err, "proxy failed"); + (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()) + } + } +} + +fn params_set_script<'a>( + params: fastcgi_client::Params<'a>, script_name: &'a str, query: &'a str, +) -> fastcgi_client::Params<'a> { + params + .script_name(script_name) + .script_filename(create_script_filename(script_name)) + .request_uri(create_request_uri(script_name, query)) + .document_uri(script_name) +} + +fn create_script_filename(script_name: &str) -> String { + env::current_dir() + .unwrap() + .join("tests") + .join("php") + .join("fpm") + .join(script_name.trim_start_matches('/')) + .to_str() + .unwrap() + .to_owned() +} + +fn create_request_uri(script_name: &str, query: &str) -> String { + if query.is_empty() { + script_name.to_owned() + } else { + format!("{}?{}", script_name, query) + } +} + +#[instrument] +fn setup_php_fpm(index: usize, fpm_addr: &str) -> Child { + let php_fpm = env::var("PHP_FPM_BIN").unwrap_or_else(|_| "php-fpm".to_string()); + let args = [ + &php_fpm, + "-F", + // "-n", + // "-c", + // "tests/conf/php.ini", + "-y", + &format!("tests/conf/php-fpm.{}.conf", index), + "-d", + &format!("extension=target/{}/libskywalking_agent{}", TARGET, EXT), + "-d", + "skywalking_agent.enable=On", + "-d", + &format!( + "skywalking_agent.service_name=skywalking-agent-test-{}", + index + ), + "-d", + &format!("skywalking_agent.server_addr={}", COLLECTOR_GRPC_ADDRESS), + "-d", + &format!("skywalking_agent.log_level={}", PROCESS_LOG_LEVEL), + "-d", + &format!( + "skywalking_agent.log_file=/tmp/fpm-skywalking-agent.{}.log", + index + ), + "-d", + "skywalking_agent.worker_threads=3", + ]; + info!(cmd = args.join(" "), "start command"); + let child = Command::new(&args[0]) + .args(&args[1..]) + .stdin(Stdio::null()) + .stdout(File::create("/tmp/fpm-skywalking-stdout.log").unwrap()) + .stderr(File::create("/tmp/fpm-skywalking-stderr.log").unwrap()) + .spawn() + .unwrap(); + thread::sleep(Duration::from_secs(3)); + child +} + +#[instrument] +fn setup_php_swoole(index: usize) -> Child { + let php = env::var("PHP_BIN").unwrap_or_else(|_| "php".to_string()); + let args = [ + &php, + // "-n", + // "-c", + // "tests/conf/php.ini", + "-d", + &format!("extension=target/{}/libskywalking_agent{}", TARGET, EXT), + "-d", + "skywalking_agent.enable=On", + "-d", + &format!( + "skywalking_agent.service_name=skywalking-agent-test-{}-swoole", + index + ), + "-d", + &format!("skywalking_agent.server_addr={}", COLLECTOR_GRPC_ADDRESS), + "-d", + &format!("skywalking_agent.log_level={}", PROCESS_LOG_LEVEL), + "-d", + &format!( + "skywalking_agent.log_file=/tmp/swoole-skywalking-agent.{}.log", + index + ), + "-d", + "skywalking.worker_threads=3", + &format!("tests/php/swoole/main.{}.php", index), + ]; + info!(cmd = args.join(" "), "start command"); + let child = Command::new(&args[0]) + .args(&args[1..]) + .stdin(Stdio::null()) + .stdout(File::create("/tmp/swoole-skywalking-stdout.log").unwrap()) + .stderr(File::create("/tmp/swoole-skywalking-stderr.log").unwrap()) + .spawn() + .unwrap(); + thread::sleep(Duration::from_secs(3)); + child +} + +async fn kill_command(mut child: Child) -> io::Result { + if let Some(id) = child.id() { + unsafe { + kill(id as pid_t, SIGTERM); + } + } + child.wait().await +} diff --git a/tests/conf/php-fpm.1.conf b/tests/conf/php-fpm.1.conf new file mode 100644 index 0000000..71b38c0 --- /dev/null +++ b/tests/conf/php-fpm.1.conf @@ -0,0 +1,35 @@ +; Licensed to the Apache Software Foundation (ASF) under one or more +; contributor license agreements. See the NOTICE file distributed with +; this work for additional information regarding copyright ownership. +; The ASF licenses this file to You under the Apache License, Version 2.0 +; (the "License"); you may not use this file except in compliance with +; the License. You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. + +;;;;;;;;;;;;;;;;;;;;; +; FPM Configuration ; +;;;;;;;;;;;;;;;;;;;;; + +error_log = /dev/stderr +log_level = notice +daemonize = no + +;;;;;;;;;;;;;;;;;;;; +; Pool Definitions ; +;;;;;;;;;;;;;;;;;;;; + +[www] + +user = 1000 +group = 1000 +listen = 127.0.0.1:9001 +pm = ondemand +pm.max_children = 9 +pm.max_requests = 500 diff --git a/tests/conf/php-fpm.2.conf b/tests/conf/php-fpm.2.conf new file mode 100644 index 0000000..29bf4fa --- /dev/null +++ b/tests/conf/php-fpm.2.conf @@ -0,0 +1,35 @@ +; Licensed to the Apache Software Foundation (ASF) under one or more +; contributor license agreements. See the NOTICE file distributed with +; this work for additional information regarding copyright ownership. +; The ASF licenses this file to You under the Apache License, Version 2.0 +; (the "License"); you may not use this file except in compliance with +; the License. You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. + +;;;;;;;;;;;;;;;;;;;;; +; FPM Configuration ; +;;;;;;;;;;;;;;;;;;;;; + +error_log = /dev/stderr +log_level = notice +daemonize = no + +;;;;;;;;;;;;;;;;;;;; +; Pool Definitions ; +;;;;;;;;;;;;;;;;;;;; + +[www] + +user = 1000 +group = 1000 +listen = 127.0.0.1:9002 +pm = ondemand +pm.max_children = 9 +pm.max_requests = 500 diff --git a/tests/conf/php.ini b/tests/conf/php.ini new file mode 100644 index 0000000..8e03302 --- /dev/null +++ b/tests/conf/php.ini @@ -0,0 +1,236 @@ +; Licensed to the Apache Software Foundation (ASF) under one or more +; contributor license agreements. See the NOTICE file distributed with +; this work for additional information regarding copyright ownership. +; The ASF licenses this file to You under the Apache License, Version 2.0 +; (the "License"); you may not use this file except in compliance with +; the License. You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. + +[PHP] + +engine = On +short_open_tag = Off +precision = 14 +output_buffering = 4096 +zlib.output_compression = Off +implicit_flush = Off +unserialize_callback_func = +serialize_precision = -1 +disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals, +disable_classes = +zend.enable_gc = On +expose_php = Off +max_execution_time = 30 +max_input_time = 60 +memory_limit = 128M +error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT +display_errors = On +display_startup_errors = Off +log_errors = On +log_errors_max_len = 1024 +ignore_repeated_errors = Off +ignore_repeated_source = Off +report_memleaks = On +html_errors = On +error_log = /dev/stderr +variables_order = "GPCS" +request_order = "GP" +register_argc_argv = Off +auto_globals_jit = On +post_max_size = 8M +auto_prepend_file = +auto_append_file = +default_mimetype = "text/html" +default_charset = "UTF-8" +doc_root = +user_dir = +enable_dl = Off +file_uploads = On +upload_max_filesize = 2M +max_file_uploads = 20 +allow_url_fopen = On +allow_url_include = Off +default_socket_timeout = 60 + +extension=mysqlnd +zend_extension=opcache +extension=pdo +extension=xml +extension=bcmath +extension=calendar +extension=ctype +extension=curl +extension=dom +extension=exif +extension=fileinfo +extension=ftp +extension=gd +extension=gettext +extension=iconv +extension=intl +extension=json +extension=mbstring +extension=mysqli +extension=pdo_mysql +extension=phar +extension=posix +extension=readline +; extension=redis +extension=shmop +extension=simplexml +extension=sockets +extension=sysvmsg +extension=sysvsem +extension=sysvshm +extension=swoole +extension=tokenizer +extension=wddx +extension=xmlreader +extension=xmlwriter +extension=xsl +extension=yaml +extension=zip + +;;;;;;;;;;;;;;;;;;; +; Module Settings ; +;;;;;;;;;;;;;;;;;;; + +[CLI Server] +cli_server.color = On + +[Date] + +[filter] + +[iconv] + +[imap] + +[intl] + +[sqlite3] + +[Pcre] + +[Pdo] + +[Pdo_mysql] +pdo_mysql.default_socket= + +[Phar] + +[mail function] +SMTP = localhost +smtp_port = 25 +mail.add_x_header = Off + +[ODBC] +odbc.allow_persistent = On +odbc.check_persistent = On +odbc.max_persistent = -1 +odbc.max_links = -1 +odbc.defaultlrl = 4096 +odbc.defaultbinmode = 1 + +[Interbase] +ibase.allow_persistent = 1 +ibase.max_persistent = -1 +ibase.max_links = -1 +ibase.timestampformat = "%Y-%m-%d %H:%M:%S" +ibase.dateformat = "%Y-%m-%d" +ibase.timeformat = "%H:%M:%S" + +[MySQLi] +mysqli.max_persistent = -1 +mysqli.allow_persistent = On +mysqli.max_links = -1 +mysqli.default_port = 3306 +mysqli.default_socket = +mysqli.default_host = +mysqli.default_user = +mysqli.default_pw = +mysqli.reconnect = Off + +[mysqlnd] +mysqlnd.collect_statistics = On +mysqlnd.collect_memory_statistics = Off + +[OCI8] + +[PostgreSQL] +pgsql.allow_persistent = On +pgsql.auto_reset_persistent = Off +pgsql.max_persistent = -1 +pgsql.max_links = -1 +pgsql.ignore_notice = 0 +pgsql.log_notice = 0 + +[bcmath] +bcmath.scale = 0 + +[browscap] + +[Session] +session.save_handler = files +session.use_strict_mode = 0 +session.use_cookies = 1 +session.use_only_cookies = 1 +session.name = PHPSESSID +session.auto_start = 0 +session.cookie_lifetime = 0 +session.cookie_path = / +session.cookie_domain = +session.cookie_httponly = +session.cookie_samesite = +session.serialize_handler = php +session.gc_probability = 0 +session.gc_divisor = 1000 +session.gc_maxlifetime = 1440 +session.referer_check = +session.cache_limiter = nocache +session.cache_expire = 180 +session.use_trans_sid = 0 +session.sid_length = 26 +session.trans_sid_tags = "a=href,area=href,frame=src,form=" +session.sid_bits_per_character = 5 + +[Assertion] +zend.assertions = 1 +assert.exception = 1 + +[COM] + +[mbstring] + +[gd] + +[exif] + +[Tidy] +tidy.clean_output = Off + +[soap] +soap.wsdl_cache_enabled=1 +soap.wsdl_cache_dir="/tmp" +soap.wsdl_cache_ttl=86400 +soap.wsdl_cache_limit = 5 + +[sysvshm] + +[ldap] +ldap.max_links = -1 + +[dba] + +[opcache] + +[curl] + +[openssl] diff --git a/tests/data/expected_context.yaml b/tests/data/expected_context.yaml new file mode 100644 index 0000000..bc3470c --- /dev/null +++ b/tests/data/expected_context.yaml @@ -0,0 +1,1554 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +segmentItems: + - serviceName: skywalking-agent-test-1 + segmentSize: 17 + segments: + - segmentId: "not null" + spans: + - operationName: GET:/index.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9011/index.php" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + refs: + - { + parentEndpoint: "GET:/curl.enter.php", + networkAddress: "", + refType: CrossProcess, + parentSpanId: 1, + parentTraceSegmentId: "not null", + parentServiceInstance: "not null", + parentService: skywalking-agent-test-1, + traceId: "not null", + } + - segmentId: "not null" + spans: + - operationName: POST:/curl.test.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { + key: url, + value: "http://127.0.0.1:9011/curl.test.php?single=1", + } + - { key: http.method, value: POST } + - { key: http.status_code, value: "200" } + refs: + - { + parentEndpoint: "GET:/curl.enter.php", + networkAddress: "", + refType: CrossProcess, + parentSpanId: 2, + parentTraceSegmentId: "not null", + parentServiceInstance: "not null", + parentService: skywalking-agent-test-1, + traceId: "not null", + } + - segmentId: "not null" + spans: + - operationName: POST:/curl.test.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { + key: url, + value: "http://127.0.0.1:9011/curl.test.php?single=2", + } + - { key: http.method, value: POST } + - { key: http.status_code, value: "200" } + refs: + - { + parentEndpoint: "GET:/curl.enter.php", + networkAddress: "", + refType: CrossProcess, + parentSpanId: 3, + parentTraceSegmentId: "not null", + parentServiceInstance: "not null", + parentService: skywalking-agent-test-1, + traceId: "not null", + } + - segmentId: "not null" + spans: + - operationName: GET:/not-exists.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: true + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { + key: url, + value: "http://127.0.0.1:9011/not-exists.php?single=3", + } + - { key: http.method, value: GET } + - { key: http.status_code, value: "404" } + refs: + - { + parentEndpoint: "GET:/curl.enter.php", + networkAddress: "", + refType: CrossProcess, + parentSpanId: 4, + parentTraceSegmentId: "not null", + parentServiceInstance: "not null", + parentService: skywalking-agent-test-1, + traceId: "not null", + } + - segmentId: "not null" + spans: + - operationName: GET:/index.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9011/index.php" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + refs: + - { + parentEndpoint: "GET:/guzzle.php", + networkAddress: "", + refType: CrossProcess, + parentSpanId: 1, + parentTraceSegmentId: "not null", + parentServiceInstance: "not null", + parentService: skywalking-agent-test-2, + traceId: "not null", + } + - segmentId: "not null" + spans: + - operationName: /index.php + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8002 + isError: false + spanType: Exit + peer: 127.0.0.1:9011 + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9011/index.php" } + - { key: status_code, value: "200" } + - operationName: /curl.test.php + parentSpanId: 0 + spanId: 2 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8002 + isError: false + spanType: Exit + peer: 127.0.0.1:9011 + skipAnalysis: false + tags: + - { + key: url, + value: "http://127.0.0.1:9011/curl.test.php?single=1", + } + - { key: status_code, value: "200" } + - operationName: /curl.test.php + parentSpanId: 0 + spanId: 3 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8002 + isError: false + spanType: Exit + peer: 127.0.0.1:9011 + skipAnalysis: false + tags: + - { + key: url, + value: "http://127.0.0.1:9011/curl.test.php?single=2", + } + - { key: status_code, value: "200" } + - operationName: /not-exists.php + parentSpanId: 0 + spanId: 4 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8002 + isError: true + spanType: Exit + peer: 127.0.0.1:9011 + skipAnalysis: false + tags: + - { + key: url, + value: "http://127.0.0.1:9011/not-exists.php?single=3", + } + - { key: status_code, value: "500" } + - operationName: /guzzle.php + parentSpanId: 0 + spanId: 5 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8002 + isError: false + spanType: Exit + peer: 127.0.0.1:9012 + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9012/guzzle.php" } + - { key: status_code, value: "200" } + - operationName: GET:/curl.enter.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9011/curl.enter.php" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + - segmentId: "not null" + spans: + - operationName: GET:/not-exists.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: true + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { + key: url, + value: "http://127.0.0.1:9011/not-exists.php?multi=3", + } + - { key: http.method, value: GET } + - { key: http.status_code, value: "404" } + refs: + - { + parentEndpoint: "GET:/curl-multi.enter.php", + networkAddress: "", + refType: CrossProcess, + parentSpanId: 3, + parentTraceSegmentId: "not null", + parentServiceInstance: "not null", + parentService: skywalking-agent-test-1, + traceId: "not null", + } + - segmentId: "not null" + spans: + - operationName: POST:/curl.test.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { + key: url, + value: "http://127.0.0.1:9011/curl.test.php?multi=1", + } + - { key: http.method, value: POST } + - { key: http.status_code, value: "200" } + refs: + - { + parentEndpoint: "GET:/curl-multi.enter.php", + networkAddress: "", + refType: CrossProcess, + parentSpanId: 1, + parentTraceSegmentId: "not null", + parentServiceInstance: "not null", + parentService: skywalking-agent-test-1, + traceId: "not null", + } + - segmentId: "not null" + spans: + - operationName: POST:/curl.test.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { + key: url, + value: "http://127.0.0.1:9011/curl.test.php?multi=2", + } + - { key: http.method, value: POST } + - { key: http.status_code, value: "200" } + refs: + - { + parentEndpoint: "GET:/curl-multi.enter.php", + networkAddress: "", + refType: CrossProcess, + parentSpanId: 2, + parentTraceSegmentId: "not null", + parentServiceInstance: "not null", + parentService: skywalking-agent-test-1, + traceId: "not null", + } + - segmentId: "not null" + spans: + - operationName: /not-exists.php + parentSpanId: 0 + spanId: 3 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8002 + isError: true + spanType: Exit + peer: 127.0.0.1:9011 + skipAnalysis: false + tags: + - { + key: url, + value: "http://127.0.0.1:9011/not-exists.php?multi=3", + } + - { key: status_code, value: "500" } + - operationName: /curl.test.php + parentSpanId: 0 + spanId: 2 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8002 + isError: false + spanType: Exit + peer: 127.0.0.1:9011 + skipAnalysis: false + tags: + - { + key: url, + value: "http://127.0.0.1:9011/curl.test.php?multi=2", + } + - { key: status_code, value: "200" } + - operationName: /curl.test.php + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8002 + isError: false + spanType: Exit + peer: 127.0.0.1:9011 + skipAnalysis: false + tags: + - { + key: url, + value: "http://127.0.0.1:9011/curl.test.php?multi=1", + } + - { key: status_code, value: "200" } + - operationName: GET:/curl-multi.enter.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { + key: url, + value: "http://127.0.0.1:9011/curl-multi.enter.php", + } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + - segmentId: "not null" + spans: + - operationName: PDO->exec + parentSpanId: 0 + spanId: 1 + spanLayer: Database + startTime: gt 0 + endTime: gt 0 + componentId: 8003 + isError: false + spanType: Exit + peer: 127.0.0.1:3306 + skipAnalysis: false + tags: + - { key: db.type, value: mysql } + - { + key: db.data_source, + value: "dbname=skywalking;host=127.0.0.1;port=3306", + } + - { key: db.statement, value: SELECT 1 } + - operationName: PDO->prepare + parentSpanId: 0 + spanId: 2 + spanLayer: Database + startTime: gt 0 + endTime: gt 0 + componentId: 8003 + isError: false + spanType: Exit + peer: 127.0.0.1:3306 + skipAnalysis: false + tags: + - { key: db.type, value: mysql } + - { + key: db.data_source, + value: "dbname=skywalking;host=127.0.0.1:3306", + } + - { + key: db.statement, + value: "SELECT * FROM `mysql`.`user` WHERE `User` = :user", + } + - operationName: PDOStatement->execute + parentSpanId: 0 + spanId: 3 + spanLayer: Database + startTime: gt 0 + endTime: gt 0 + componentId: 8003 + isError: false + spanType: Exit + peer: 127.0.0.1:3306 + skipAnalysis: false + tags: + - { key: db.type, value: mysql } + - { + key: db.data_source, + value: "dbname=skywalking;host=127.0.0.1:3306", + } + - { + key: db.statement, + value: "SELECT * FROM `mysql`.`user` WHERE `User` = :user", + } + - operationName: PDOStatement->fetchAll + parentSpanId: 0 + spanId: 4 + spanLayer: Database + startTime: gt 0 + endTime: gt 0 + componentId: 8003 + isError: false + spanType: Exit + peer: 127.0.0.1:3306 + skipAnalysis: false + tags: + - { key: db.type, value: mysql } + - { + key: db.data_source, + value: "dbname=skywalking;host=127.0.0.1:3306", + } + - { + key: db.statement, + value: "SELECT * FROM `mysql`.`user` WHERE `User` = :user", + } + - operationName: PDO->prepare + parentSpanId: 0 + spanId: 5 + spanLayer: Database + startTime: gt 0 + endTime: gt 0 + componentId: 8003 + isError: false + spanType: Exit + peer: 127.0.0.1:3306 + skipAnalysis: false + tags: + - { key: db.type, value: mysql } + - { + key: db.data_source, + value: "dbname=skywalking;host=127.0.0.1:3306;", + } + - { + key: db.statement, + value: "SELECT * FROM `mysql`.`user` WHERE `User` = :user", + } + - operationName: PDOStatement->execute + parentSpanId: 0 + spanId: 6 + spanLayer: Database + startTime: gt 0 + endTime: gt 0 + componentId: 8003 + isError: false + spanType: Exit + peer: 127.0.0.1:3306 + skipAnalysis: false + tags: + - { key: db.type, value: mysql } + - { + key: db.data_source, + value: "dbname=skywalking;host=127.0.0.1:3306;", + } + - { + key: db.statement, + value: "SELECT * FROM `mysql`.`user` WHERE `User` = :user", + } + - operationName: PDOStatement->fetchAll + parentSpanId: 0 + spanId: 7 + spanLayer: Database + startTime: gt 0 + endTime: gt 0 + componentId: 8003 + isError: false + spanType: Exit + peer: 127.0.0.1:3306 + skipAnalysis: false + tags: + - { key: db.type, value: mysql } + - { + key: db.data_source, + value: "dbname=skywalking;host=127.0.0.1:3306;", + } + - { + key: db.statement, + value: "SELECT * FROM `mysql`.`user` WHERE `User` = :user", + } + - operationName: PDO->prepare + parentSpanId: 0 + spanId: 8 + spanLayer: Database + startTime: gt 0 + endTime: gt 0 + componentId: 8003 + isError: false + spanType: Exit + peer: 127.0.0.1:3306 + skipAnalysis: false + tags: + - { key: db.type, value: mysql } + - { + key: db.data_source, + value: "dbname=skywalking;host=127.0.0.1;port=3306", + } + - { + key: db.statement, + value: "SELECT * FROM not_exist", + } + - operationName: PDOStatement->execute + parentSpanId: 0 + spanId: 9 + spanLayer: Database + startTime: gt 0 + endTime: gt 0 + componentId: 8003 + isError: true + spanType: Exit + peer: 127.0.0.1:3306 + skipAnalysis: false + tags: + - { key: db.type, value: mysql } + - { + key: db.data_source, + value: "dbname=skywalking;host=127.0.0.1;port=3306", + } + - { + key: db.statement, + value: "SELECT * FROM not_exist", + } + logs: + - logEvent: + - { key: SQLSTATE, value: 42S02 } + - { key: Error Code, value: '1146' } + - { key: Error, value: "Table 'skywalking.not_exist' doesn't exist" } + - operationName: GET:/pdo.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9011/pdo.php" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + - segmentId: "not null" + spans: + - operationName: "Predis\\Client->auth" + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 8006 + isError: false + spanType: Exit + peer: 127.0.0.1:6379 + skipAnalysis: false + tags: + - { key: cache.type, value: redis } + - { key: cache.cmd, value: AUTH } + - operationName: "Predis\\Client->set" + parentSpanId: 0 + spanId: 2 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 8006 + isError: false + spanType: Exit + peer: 127.0.0.1:6379 + skipAnalysis: false + tags: + - { key: cache.type, value: redis } + - { key: cache.cmd, value: SET } + - { key: cache.op, value: write } + - { key: cache.key, value: foo } + - operationName: "Predis\\Client->get" + parentSpanId: 0 + spanId: 3 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 8006 + isError: false + spanType: Exit + peer: 127.0.0.1:6379 + skipAnalysis: false + tags: + - { key: cache.type, value: redis } + - { key: cache.cmd, value: GET } + - { key: cache.op, value: read } + - { key: cache.key, value: foo } + - operationName: "Predis\\Client->get" + parentSpanId: 0 + spanId: 4 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 8006 + isError: false + spanType: Exit + peer: 127.0.0.1:6379 + skipAnalysis: false + tags: + - { key: cache.type, value: redis } + - { key: cache.cmd, value: GET } + - { key: cache.op, value: read } + - { key: cache.key, value: not-exists } + - operationName: GET:/predis.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9011/predis.php" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + - segmentId: 'not null' + spans: + - operationName: mysqli->query + parentSpanId: 0 + spanId: 1 + spanLayer: Database + startTime: gt 0 + endTime: gt 0 + componentId: 8004 + isError: false + spanType: Exit + peer: 127.0.0.1:3306 + skipAnalysis: false + tags: + - {key: db.type, value: mysql} + - { + key: db.statement, + value: "SELECT 1", + } + - operationName: mysqli->query + parentSpanId: 0 + spanId: 2 + spanLayer: Database + startTime: gt 0 + endTime: gt 0 + componentId: 8004 + isError: false + spanType: Exit + peer: 127.0.0.1:3306 + skipAnalysis: false + tags: + - {key: db.type, value: mysql} + - { + key: db.statement, + value: "SELECT * FROM `mysql`.`user` WHERE `User` = 'root'", + } + - operationName: GET:/mysqli.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9011/mysqli.php" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + - segmentId: 'not null' + spans: + - operationName: Memcached->set + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 20 + isError: false + spanType: Exit + peer: 127.0.0.1:11211 + skipAnalysis: false + tags: + - { key: cache.type, value: memcache } + - { key: cache.cmd, value: set } + - { key: cache.op, value: write } + - { key: cache.key, value: foo } + - operationName: Memcached->set + parentSpanId: 0 + spanId: 2 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 20 + isError: false + spanType: Exit + peer: 127.0.0.1:11211 + skipAnalysis: false + tags: + - { key: cache.type, value: memcache } + - { key: cache.cmd, value: set } + - { key: cache.op, value: write } + - { key: cache.key, value: bar } + - operationName: Memcached->get + parentSpanId: 0 + spanId: 3 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 20 + isError: false + spanType: Exit + peer: 127.0.0.1:11211 + skipAnalysis: false + tags: + - { key: cache.type, value: memcache } + - { key: cache.cmd, value: get } + - { key: cache.op, value: read } + - { key: cache.key, value: foo } + - operationName: Memcached->get + parentSpanId: 0 + spanId: 4 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 20 + isError: false + spanType: Exit + peer: 127.0.0.1:11211 + skipAnalysis: false + tags: + - { key: cache.type, value: memcache } + - { key: cache.cmd, value: get } + - { key: cache.op, value: read } + - { key: cache.key, value: bar } + - operationName: Memcached->setMulti + parentSpanId: 0 + spanId: 5 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 20 + isError: false + spanType: Exit + peer: "" + skipAnalysis: false + tags: + - { key: cache.type, value: memcache } + - { key: cache.cmd, value: set } + - { key: cache.op, value: write } + - operationName: Memcached->get + parentSpanId: 0 + spanId: 6 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 20 + isError: true + spanType: Exit + peer: 127.0.0.1:11211 + skipAnalysis: false + tags: + - { key: cache.type, value: memcache } + - { key: cache.cmd, value: get } + - { key: cache.op, value: read } + - { key: cache.key, value: not-exists } + logs: + - logEvent: + - { key: ResultCode, value: "16" } + - { key: ResultMessage, value: NOT FOUND } + - operationName: GET:/memcached.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9011/memcached.php" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + - segmentId: "not null" + spans: + - operationName: Redis->connect + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 7 + isError: false + spanType: Exit + peer: "127.0.0.1:6379" + skipAnalysis: false + tags: + - key: cache.type + value: redis + - operationName: Redis->auth + parentSpanId: 0 + spanId: 2 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 7 + isError: false + spanType: Exit + peer: 127.0.0.1:6379 + skipAnalysis: false + tags: + - { key: cache.type, value: redis } + - { key: cache.cmd, value: AUTH } + - operationName: Redis->mset + parentSpanId: 0 + spanId: 3 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 7 + isError: false + spanType: Exit + peer: 127.0.0.1:6379 + skipAnalysis: false + tags: + - { key: cache.type, value: redis } + - { key: cache.cmd, value: MSET } + - { key: cache.op, value: write } + - operationName: Redis->get + parentSpanId: 0 + spanId: 4 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 7 + isError: false + spanType: Exit + peer: 127.0.0.1:6379 + skipAnalysis: false + tags: + - { key: cache.type, value: redis } + - { key: cache.cmd, value: GET } + - { key: cache.op, value: read } + - { key: cache.key, value: key0 } + - operationName: Redis->get + parentSpanId: 0 + spanId: 5 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 7 + isError: false + spanType: Exit + peer: 127.0.0.1:6379 + skipAnalysis: false + tags: + - { key: cache.type, value: redis } + - { key: cache.cmd, value: GET } + - { key: cache.op, value: read } + - { key: cache.key, value: key1 } + - operationName: GET:/redis.succ.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9011/redis.succ.php" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + - segmentId: "not null" + spans: + - operationName: Redis->connect + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 7 + isError: false + spanType: Exit + peer: "127.0.0.1:6379" + skipAnalysis: false + tags: + - { key: cache.type, value: redis } + - operationName: Redis->set + parentSpanId: 0 + spanId: 2 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 7 + isError: true + spanType: Exit + peer: 127.0.0.1:6379 + skipAnalysis: false + tags: + - { key: cache.type, value: redis } + - { key: cache.cmd, value: SET } + - { key: cache.op, value: write } + - { key: cache.key, value: foo } + logs: + - logEvent: + - { key: Exception Class, value: RedisException } + - { + key: Exception Message, + value: NOAUTH Authentication required., + } + - operationName: GET:/redis.fail.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9011/redis.fail.php" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + - segmentId: "not null" + spans: + - operationName: "PhpAmqpLib\\Channel\\AMQPChannel->basic_publish" + parentSpanId: 0 + spanId: 1 + spanLayer: MQ + startTime: gt 0 + endTime: gt 0 + componentId: 144 + isError: false + spanType: Exit + peer: 127.0.0.1:5672 + skipAnalysis: false + tags: + - { key: mq.broker, value: "127.0.0.1:5672" } + - { key: mq.topic, value: "" } + - { key: mq.queue, value: queue_test } + - operationName: "PhpAmqpLib\\Channel\\AMQPChannel->basic_publish" + parentSpanId: 0 + spanId: 2 + spanLayer: MQ + startTime: gt 0 + endTime: gt 0 + componentId: 144 + isError: false + spanType: Exit + peer: 127.0.0.1:5672 + skipAnalysis: false + tags: + - { key: mq.broker, value: "127.0.0.1:5672" } + - { key: mq.topic, value: exchange_test } + - { key: mq.queue, value: routing_test } + - operationName: "PhpAmqpLib\\Channel\\AMQPChannel->basic_publish" + parentSpanId: 0 + spanId: 3 + spanLayer: MQ + startTime: gt 0 + endTime: gt 0 + componentId: 144 + isError: false + spanType: Exit + peer: 127.0.0.1:5672 + skipAnalysis: false + tags: + - { key: mq.broker, value: "127.0.0.1:5672" } + - { key: mq.topic, value: "" } + - { key: mq.queue, value: not_exists } + - operationName: GET:/rabbitmq.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9011/rabbitmq.php" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + - serviceName: skywalking-agent-test-2 + segmentSize: 1 + segments: + - segmentId: "not null" + spans: + - operationName: /index.php + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8002 + isError: false + spanType: Exit + peer: 127.0.0.1:9011 + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9011/index.php" } + - { key: status_code, value: "200" } + - operationName: GET:/guzzle.php + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9012/guzzle.php" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + refs: + - { + parentEndpoint: "GET:/curl.enter.php", + networkAddress: "", + refType: CrossProcess, + parentSpanId: 5, + parentTraceSegmentId: "not null", + parentServiceInstance: "not null", + parentService: skywalking-agent-test-1, + traceId: "not null", + } + - serviceName: skywalking-agent-test-1-swoole + segmentSize: 2 + segments: + - segmentId: "not null" + spans: + - operationName: GET:/ + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9501/?swoole=1" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + refs: + - { + parentEndpoint: "GET:/curl", + networkAddress: "", + refType: CrossProcess, + parentSpanId: 1, + parentTraceSegmentId: "not null", + parentServiceInstance: "not null", + parentService: skywalking-agent-test-1-swoole, + traceId: "not null", + } + - segmentId: "not null" + spans: + - operationName: / + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8002 + isError: false + spanType: Exit + peer: 127.0.0.1:9501 + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9501/?swoole=1" } + - { key: status_code, value: "200" } + - operationName: / + parentSpanId: 0 + spanId: 2 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8002 + isError: false + spanType: Exit + peer: 127.0.0.1:9502 + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9502/" } + - { key: status_code, value: "200" } + - operationName: GET:/curl + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9501/curl" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + - serviceName: skywalking-agent-test-2-swoole + segmentSize: 8 + segments: + - segmentId: "not null" + spans: + - operationName: GET:/ + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9502/" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + refs: + - { + parentEndpoint: "GET:/curl", + networkAddress: "", + refType: CrossProcess, + parentSpanId: 2, + parentTraceSegmentId: "not null", + parentServiceInstance: "not null", + parentService: skywalking-agent-test-1-swoole, + traceId: "not null", + } + - segmentId: "not null" + spans: + - operationName: GET:/ + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9502/?swoole=2" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + refs: + - { + parentEndpoint: "GET:/curl", + networkAddress: "", + refType: CrossProcess, + parentSpanId: 1, + parentTraceSegmentId: "not null", + parentServiceInstance: "not null", + parentService: skywalking-agent-test-2-swoole, + traceId: "not null", + } + - segmentId: "not null" + spans: + - operationName: / + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8002 + isError: false + spanType: Exit + peer: 127.0.0.1:9502 + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9502/?swoole=2" } + - { key: status_code, value: "200" } + - operationName: GET:/curl + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9502/curl" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + - segmentId: "not null" + spans: + - operationName: PDO->exec + parentSpanId: 0 + spanId: 1 + spanLayer: Database + startTime: gt 0 + endTime: gt 0 + componentId: 8003 + isError: false + spanType: Exit + peer: 127.0.0.1:3306 + skipAnalysis: false + tags: + - { key: db.type, value: mysql } + - { + key: db.data_source, + value: dbname=skywalking;host=127.0.0.1;port=3306, + } + - { key: db.statement, value: SELECT 1 } + - operationName: GET:/pdo + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9502/pdo" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + - segmentId: "not null" + spans: + - operationName: mysqli->query + parentSpanId: 0 + spanId: 1 + spanLayer: Database + startTime: gt 0 + endTime: gt 0 + componentId: 8004 + isError: false + spanType: Exit + peer: 127.0.0.1:3306 + skipAnalysis: false + tags: + - { key: db.type, value: mysql } + - { key: db.statement, value: SELECT 1 } + - operationName: GET:/mysqli + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9502/mysqli" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + - segmentId: "not null" + spans: + - operationName: Memcached->set + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 20 + isError: false + spanType: Exit + peer: 127.0.0.1:11211 + skipAnalysis: false + tags: + - { key: cache.type, value: memcache } + - { key: cache.cmd, value: set } + - { key: cache.op, value: write } + - { key: cache.key, value: foo000 } + - operationName: Memcached->get + parentSpanId: 0 + spanId: 2 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 20 + isError: false + spanType: Exit + peer: 127.0.0.1:11211 + skipAnalysis: false + tags: + - { key: cache.type, value: memcache } + - { key: cache.cmd, value: get } + - { key: cache.op, value: read } + - { key: cache.key, value: foo000 } + - operationName: GET:/memcached + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9502/memcached" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + - segmentId: "not null" + spans: + - operationName: Redis->connect + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 7 + isError: false + spanType: Exit + peer: 127.0.0.1:6379 + skipAnalysis: false + tags: + - { key: cache.type, value: redis } + - operationName: Redis->auth + parentSpanId: 0 + spanId: 2 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 7 + isError: false + spanType: Exit + peer: 127.0.0.1:6379 + skipAnalysis: false + tags: + - { key: cache.type, value: redis } + - { key: cache.cmd, value: AUTH } + - operationName: Redis->set + parentSpanId: 0 + spanId: 3 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 7 + isError: false + spanType: Exit + peer: 127.0.0.1:6379 + skipAnalysis: false + tags: + - { key: cache.type, value: redis } + - { key: cache.cmd, value: SET } + - { key: cache.op, value: write } + - { key: cache.key, value: foo001 } + - operationName: Redis->get + parentSpanId: 0 + spanId: 4 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 7 + isError: false + spanType: Exit + peer: 127.0.0.1:6379 + skipAnalysis: false + tags: + - { key: cache.type, value: redis } + - { key: cache.cmd, value: GET } + - { key: cache.op, value: read } + - { key: cache.key, value: foo001 } + - operationName: GET:/redis + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9502/redis" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } + - segmentId: "not null" + spans: + - operationName: "Predis\\Client->auth" + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 8006 + isError: false + spanType: Exit + peer: 127.0.0.1:6379 + skipAnalysis: false + tags: + - { key: cache.type, value: redis } + - { key: cache.cmd, value: AUTH } + - operationName: "Predis\\Client->set" + parentSpanId: 0 + spanId: 2 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 8006 + isError: false + spanType: Exit + peer: 127.0.0.1:6379 + skipAnalysis: false + tags: + - { key: cache.type, value: redis } + - { key: cache.cmd, value: SET } + - { key: cache.op, value: write } + - { key: cache.key, value: foo002 } + - operationName: "Predis\\Client->get" + parentSpanId: 0 + spanId: 3 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 8006 + isError: false + spanType: Exit + peer: 127.0.0.1:6379 + skipAnalysis: false + tags: + - { key: cache.type, value: redis } + - { key: cache.cmd, value: GET } + - { key: cache.op, value: read } + - { key: cache.key, value: foo002 } + - operationName: GET:/predis + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 8001 + isError: false + spanType: Entry + peer: "" + skipAnalysis: false + tags: + - { key: url, value: "http://127.0.0.1:9502/predis" } + - { key: http.method, value: GET } + - { key: http.status_code, value: "200" } diff --git a/tests/e2e.rs b/tests/e2e.rs new file mode 100644 index 0000000..3ae9e99 --- /dev/null +++ b/tests/e2e.rs @@ -0,0 +1,220 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod common; + +use crate::common::{ + COLLECTOR_HTTP_ADDRESS, HTTP_CLIENT, PROXY_SERVER_1_ADDRESS, SWOOLE_SERVER_1_ADDRESS, + SWOOLE_SERVER_2_ADDRESS, +}; +use reqwest::{header::CONTENT_TYPE, RequestBuilder, StatusCode}; +use std::{ + panic::{catch_unwind, resume_unwind}, + time::Duration, +}; +use tokio::{fs::File, runtime::Handle, task, time::sleep}; +use tracing::info; + +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn e2e() { + let fixture = common::setup().await; + + // TODO Prefer to listen the server ready signal. + sleep(Duration::from_secs(5)).await; + + let result = catch_unwind(|| { + task::block_in_place(|| { + Handle::current().block_on(run_e2e()); + }); + }); + + common::teardown(fixture).await; + + if let Err(e) = result { + resume_unwind(e); + } +} + +async fn run_e2e() { + request_fpm_curl().await; + request_fpm_curl_multi().await; + request_fpm_pdo().await; + request_fpm_predis().await; + request_fpm_mysqli().await; + request_fpm_memcached().await; + request_fpm_redis().await; + request_fpm_rabbitmq().await; + request_swoole_curl().await; + request_swoole_2_curl().await; + request_swoole_2_pdo().await; + request_swoole_2_mysqli().await; + request_swoole_2_memcached().await; + request_swoole_2_redis().await; + request_swoole_2_predis().await; + sleep(Duration::from_secs(3)).await; + request_collector_validate().await; +} + +async fn request_fpm_curl() { + request_common( + HTTP_CLIENT.get(format!("http://{}/curl.enter.php", PROXY_SERVER_1_ADDRESS)), + "ok", + ) + .await; +} + +async fn request_fpm_curl_multi() { + request_common( + HTTP_CLIENT.get(format!( + "http://{}/curl-multi.enter.php", + PROXY_SERVER_1_ADDRESS + )), + "ok", + ) + .await; +} + +async fn request_fpm_pdo() { + request_common( + HTTP_CLIENT.get(format!("http://{}/pdo.php", PROXY_SERVER_1_ADDRESS)), + "ok", + ) + .await; +} + +async fn request_fpm_mysqli() { + request_common( + HTTP_CLIENT.get(format!("http://{}/mysqli.php", PROXY_SERVER_1_ADDRESS)), + "ok", + ) + .await; +} + +async fn request_fpm_predis() { + request_common( + HTTP_CLIENT.get(format!("http://{}/predis.php", PROXY_SERVER_1_ADDRESS)), + "ok", + ) + .await; +} + +async fn request_fpm_memcached() { + request_common( + HTTP_CLIENT.get(format!("http://{}/memcached.php", PROXY_SERVER_1_ADDRESS)), + "ok", + ) + .await; +} + +async fn request_fpm_redis() { + request_common( + HTTP_CLIENT.get(format!("http://{}/redis.succ.php", PROXY_SERVER_1_ADDRESS)), + "ok", + ) + .await; + + request_common( + HTTP_CLIENT.get(format!("http://{}/redis.fail.php", PROXY_SERVER_1_ADDRESS)), + "ok", + ) + .await; +} + +async fn request_fpm_rabbitmq() { + request_common( + HTTP_CLIENT.get(format!("http://{}/rabbitmq.php", PROXY_SERVER_1_ADDRESS)), + "ok", + ) + .await; +} + +async fn request_swoole_curl() { + request_common( + HTTP_CLIENT.get(format!("http://{}/curl", SWOOLE_SERVER_1_ADDRESS)), + "ok", + ) + .await; +} + +async fn request_swoole_2_curl() { + request_common( + HTTP_CLIENT.get(format!("http://{}/curl", SWOOLE_SERVER_2_ADDRESS)), + "ok", + ) + .await; +} + +async fn request_swoole_2_pdo() { + request_common( + HTTP_CLIENT.get(format!("http://{}/pdo", SWOOLE_SERVER_2_ADDRESS)), + "ok", + ) + .await; +} + +async fn request_swoole_2_mysqli() { + request_common( + HTTP_CLIENT.get(format!("http://{}/mysqli", SWOOLE_SERVER_2_ADDRESS)), + "ok", + ) + .await; +} + +async fn request_swoole_2_memcached() { + request_common( + HTTP_CLIENT.get(format!("http://{}/memcached", SWOOLE_SERVER_2_ADDRESS)), + "ok", + ) + .await; +} + +async fn request_swoole_2_redis() { + request_common( + HTTP_CLIENT.get(format!("http://{}/redis", SWOOLE_SERVER_2_ADDRESS)), + "ok", + ) + .await; +} + +async fn request_swoole_2_predis() { + request_common( + HTTP_CLIENT.get(format!("http://{}/predis", SWOOLE_SERVER_2_ADDRESS)), + "ok", + ) + .await; +} + +async fn request_collector_validate() { + request_common( + HTTP_CLIENT + .post(format!("http://{}/dataValidate", COLLECTOR_HTTP_ADDRESS)) + .header(CONTENT_TYPE, "text/yaml") + .body( + File::open("./tests/data/expected_context.yaml") + .await + .unwrap(), + ), + "success", + ) + .await; +} + +async fn request_common(request_builder: RequestBuilder, actual_content: impl Into) { + let response = request_builder.send().await.unwrap(); + let status = response.status(); + let content = response.text().await.unwrap(); + info!(content, "response content"); + assert_eq!((status, content), (StatusCode::OK, actual_content.into())); +} diff --git a/tests/php/composer.json b/tests/php/composer.json new file mode 100644 index 0000000..a734774 --- /dev/null +++ b/tests/php/composer.json @@ -0,0 +1,18 @@ +{ + "name": "skywalking-agent/php-test", + "type": "project", + "authors": [ + { + "name": "jmjoy", + "email": "jmjoy@apache.org" + } + ], + "require": { + "php": ">=7.2", + "ext-swoole": ">=4.5", + "predis/predis": "^2.0", + "guzzlehttp/guzzle": "^7.4", + "webmozart/assert": "^1.11", + "php-amqplib/php-amqplib": "^3.5" + } +} diff --git a/tests/php/composer.lock b/tests/php/composer.lock new file mode 100644 index 0000000..dd06a7a --- /dev/null +++ b/tests/php/composer.lock @@ -0,0 +1,1054 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "476a32189446bfa8cad519f74dbc3382", + "packages": [ + { + "name": "guzzlehttp/guzzle", + "version": "7.4.5", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "1dd98b0564cb3f6bd16ce683cb755f94c10fbd82" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/1dd98b0564cb3f6bd16ce683cb755f94c10fbd82", + "reference": "1dd98b0564cb3f6bd16ce683cb755f94c10fbd82", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5", + "guzzlehttp/psr7": "^1.9 || ^2.4", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "ext-curl": "*", + "php-http/client-integration-tests": "^3.0", + "phpunit/phpunit": "^8.5.5 || ^9.3.5", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.4-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.4.5" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2022-06-20T22:16:13+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "1.5.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/fe752aedc9fd8fcca3fe7ad05d419d32998a06da", + "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "symfony/phpunit-bridge": "^4.4 || ^5.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/1.5.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2021-10-22T20:56:57+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.5.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "b635f279edd83fc275f822a1188157ffea568ff6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6", + "reference": "b635f279edd83fc275f822a1188157ffea568ff6", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.5.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2023-04-17T16:11:26+00:00" + }, + { + "name": "paragonie/constant_time_encoding", + "version": "v2.6.3", + "source": { + "type": "git", + "url": "https://github.com/paragonie/constant_time_encoding.git", + "reference": "58c3f47f650c94ec05a151692652a868995d2938" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/58c3f47f650c94ec05a151692652a868995d2938", + "reference": "58c3f47f650c94ec05a151692652a868995d2938", + "shasum": "" + }, + "require": { + "php": "^7|^8" + }, + "require-dev": { + "phpunit/phpunit": "^6|^7|^8|^9", + "vimeo/psalm": "^1|^2|^3|^4" + }, + "type": "library", + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com", + "role": "Maintainer" + }, + { + "name": "Steve 'Sc00bz' Thomas", + "email": "steve@tobtu.com", + "homepage": "https://www.tobtu.com", + "role": "Original Developer" + } + ], + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base16", + "base32", + "base32_decode", + "base32_encode", + "base64", + "base64_decode", + "base64_encode", + "bin2hex", + "encoding", + "hex", + "hex2bin", + "rfc4648" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/constant_time_encoding/issues", + "source": "https://github.com/paragonie/constant_time_encoding" + }, + "time": "2022-06-14T06:56:20+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v9.99.100", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", + "shasum": "" + }, + "require": { + "php": ">= 7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/random_compat/issues", + "source": "https://github.com/paragonie/random_compat" + }, + "time": "2020-10-15T08:29:30+00:00" + }, + { + "name": "php-amqplib/php-amqplib", + "version": "v3.5.3", + "source": { + "type": "git", + "url": "https://github.com/php-amqplib/php-amqplib.git", + "reference": "bccaaf8ef8bcf18b4ab41e645e92537752b887bd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/bccaaf8ef8bcf18b4ab41e645e92537752b887bd", + "reference": "bccaaf8ef8bcf18b4ab41e645e92537752b887bd", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "ext-sockets": "*", + "php": "^7.1||^8.0", + "phpseclib/phpseclib": "^2.0|^3.0" + }, + "conflict": { + "php": "7.4.0 - 7.4.1" + }, + "replace": { + "videlalvaro/php-amqplib": "self.version" + }, + "require-dev": { + "ext-curl": "*", + "nategood/httpful": "^0.2.20", + "phpunit/phpunit": "^7.5|^9.5", + "squizlabs/php_codesniffer": "^3.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpAmqpLib\\": "PhpAmqpLib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Alvaro Videla", + "role": "Original Maintainer" + }, + { + "name": "Raúl Araya", + "email": "nubeiro@gmail.com", + "role": "Maintainer" + }, + { + "name": "Luke Bakken", + "email": "luke@bakken.io", + "role": "Maintainer" + }, + { + "name": "Ramūnas Dronga", + "email": "github@ramuno.lt", + "role": "Maintainer" + } + ], + "description": "Formerly videlalvaro/php-amqplib. This library is a pure PHP implementation of the AMQP protocol. It's been tested against RabbitMQ.", + "homepage": "https://github.com/php-amqplib/php-amqplib/", + "keywords": [ + "message", + "queue", + "rabbitmq" + ], + "support": { + "issues": "https://github.com/php-amqplib/php-amqplib/issues", + "source": "https://github.com/php-amqplib/php-amqplib/tree/v3.5.3" + }, + "time": "2023-04-03T18:25:49+00:00" + }, + { + "name": "phpseclib/phpseclib", + "version": "3.0.19", + "source": { + "type": "git", + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "cc181005cf548bfd8a4896383bb825d859259f95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cc181005cf548bfd8a4896383bb825d859259f95", + "reference": "cc181005cf548bfd8a4896383bb825d859259f95", + "shasum": "" + }, + "require": { + "paragonie/constant_time_encoding": "^1|^2", + "paragonie/random_compat": "^1.4|^2.0|^9.99.99", + "php": ">=5.6.1" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "suggest": { + "ext-dom": "Install the DOM extension to load XML formatted public keys.", + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." + }, + "type": "library", + "autoload": { + "files": [ + "phpseclib/bootstrap.php" + ], + "psr-4": { + "phpseclib3\\": "phpseclib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "role": "Developer" + } + ], + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net", + "keywords": [ + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", + "sftp", + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" + ], + "support": { + "issues": "https://github.com/phpseclib/phpseclib/issues", + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.19" + }, + "funding": [ + { + "url": "https://github.com/terrafrost", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpseclib", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", + "type": "tidelift" + } + ], + "time": "2023-03-05T17:13:09+00:00" + }, + { + "name": "predis/predis", + "version": "v2.0.0", + "source": { + "type": "git", + "url": "https://github.com/predis/predis.git", + "reference": "99c253733dee9447d26257dc669d33d5ac84713d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/predis/predis/zipball/99c253733dee9447d26257dc669d33d5ac84713d", + "reference": "99c253733dee9447d26257dc669d33d5ac84713d", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.0 || ~9.4.4" + }, + "suggest": { + "ext-curl": "Allows access to Webdis when paired with phpiredis", + "ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Predis\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniele Alessandri", + "email": "suppakilla@gmail.com", + "homepage": "http://clorophilla.net", + "role": "Creator & Maintainer" + }, + { + "name": "Till Krüss", + "homepage": "https://till.im", + "role": "Maintainer" + } + ], + "description": "A flexible and feature-complete Redis client for PHP.", + "homepage": "http://github.com/predis/predis", + "keywords": [ + "nosql", + "predis", + "redis" + ], + "support": { + "issues": "https://github.com/predis/predis/issues", + "source": "https://github.com/predis/predis/tree/v2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/tillkruss", + "type": "github" + } + ], + "time": "2022-06-08T13:14:56+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "time": "2020-06-29T06:28:15+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "e616d01114759c4c489f93b099585439f795fe35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + }, + "time": "2023-04-10T20:10:41+00:00" + }, + { + "name": "psr/http-message", + "version": "1.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/1.1" + }, + "time": "2023-04-04T09:50:52+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.5.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-02T09:53:40+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=7.2", + "ext-swoole": ">=4.5" + }, + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/tests/php/fpm/curl-multi.enter.php b/tests/php/fpm/curl-multi.enter.php new file mode 100644 index 0000000..e48e378 --- /dev/null +++ b/tests/php/fpm/curl-multi.enter.php @@ -0,0 +1,114 @@ + (function () { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, "http://127.0.0.1:9011/curl.test.php?multi=1"); + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, ["foo" => "bar"]); + curl_setopt($ch, CURLOPT_HTTPHEADER, ["X-FOO:BAR"]); + return $ch; + })(), + 'callback' => function ($output) { + Assert::same($output, "ok"); + }, + ], + [ + 'curl' => (function () { + $ch = curl_init(); + curl_setopt_array($ch, [ + CURLOPT_URL => "http://127.0.0.1:9011/curl.test.php?multi=2", + CURLOPT_TIMEOUT => 10, + CURLOPT_RETURNTRANSFER => 1, + CURLOPT_POST => 1, + CURLOPT_POSTFIELDS => ["foo" => "bar"], + CURLOPT_HTTPHEADER => ["X-FOO: BAR"], + ]); + return $ch; + })(), + 'callback' => function ($output) { + Assert::same($output, "ok"); + }, + ], + [ + 'curl' => (function () { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, "http://127.0.0.1:9011/not-exists.php?multi=3"); + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HEADER, 0); + return $ch; + })(), + 'callback' => function ($output) {}, + ], + ]; + curl_multi_request($curl_callbacks); +} + +sleep(5); + +echo "ok"; + +function curl_multi_request($curl_callbacks) { + $mh = curl_multi_init(); + + foreach ($curl_callbacks as $curl_callback) { + curl_multi_add_handle($mh, $curl_callback['curl']); + } + + do { + $mrc = curl_multi_exec($mh, $active); + } while ($mrc == CURLM_CALL_MULTI_PERFORM); + + while ($active && $mrc == CURLM_OK) { + if (curl_multi_select($mh) == -1) { + return; + } + do { + $mrc = curl_multi_exec($mh, $active); + } while ($mrc == CURLM_CALL_MULTI_PERFORM); + } + + while ($info = curl_multi_info_read($mh)) { + $content = curl_multi_getcontent($info['handle']); + foreach ($curl_callbacks as $curl_callback) { + if ($curl_callback['curl'] == $info['handle']) { + call_user_func($curl_callback['callback'], $content); + break; + } + } + } + + foreach ($curl_callbacks as $curl_callback) { + curl_multi_remove_handle($mh, $curl_callback['curl']); + } + + curl_multi_close($mh); +} diff --git a/tests/php/fpm/curl.enter.php b/tests/php/fpm/curl.enter.php new file mode 100644 index 0000000..b3d51f4 --- /dev/null +++ b/tests/php/fpm/curl.enter.php @@ -0,0 +1,82 @@ + "bar"]); + curl_setopt($ch, CURLOPT_HTTPHEADER, ["X-FOO:BAR"]); + $output = curl_exec($ch); + curl_close($ch); + Assert::same($output, "ok"); +} + +{ + $ch = curl_init(); + curl_setopt_array($ch, [ + CURLOPT_URL => "http://127.0.0.1:9011/curl.test.php?single=2", + CURLOPT_TIMEOUT => 10, + CURLOPT_RETURNTRANSFER => 1, + CURLOPT_POST => 1, + CURLOPT_POSTFIELDS => ["foo" => "bar"], + CURLOPT_HTTPHEADER => ["X-FOO: BAR"], + ]); + $output = curl_exec($ch); + curl_close($ch); + Assert::same($output, "ok"); +} + +{ + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, "http://127.0.0.1:9011/not-exists.php?single=3"); + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_exec($ch); + curl_close($ch); +} + +{ + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, "http://127.0.0.1:9012/guzzle.php"); + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HEADER, 0); + $output = curl_exec($ch); + curl_close($ch); + Assert::same($output, "ok"); +} + +echo "ok"; diff --git a/tests/php/fpm/curl.test.php b/tests/php/fpm/curl.test.php new file mode 100644 index 0000000..10f27c9 --- /dev/null +++ b/tests/php/fpm/curl.test.php @@ -0,0 +1,26 @@ +request('GET', 'http://127.0.0.1:9011/index.php', [ + 'auth' => ['user', 'pass'] + ]); + Assert::same($res->getStatusCode(), 200); + Assert::eq($res->getBody(), 'ok'); +} + +echo "ok"; diff --git a/tests/php/fpm/index.php b/tests/php/fpm/index.php new file mode 100644 index 0000000..65bdc7b --- /dev/null +++ b/tests/php/fpm/index.php @@ -0,0 +1,18 @@ +addServer("127.0.0.1", 11211); + + $mc->set("foo", "Hello!"); + $mc->set("bar", "Memcached..."); + + Assert::same($mc->get("foo"), 'Hello!'); + Assert::same($mc->get("bar"), "Memcached..."); + + $mc->setMulti(array( + 'key1' => 'value1', + 'key2' => 'value2', + 'key3' => 'value3' + )); + + Assert::false($mc->get("not-exists")); +} + +echo "ok"; diff --git a/tests/php/fpm/mysqli.php b/tests/php/fpm/mysqli.php new file mode 100644 index 0000000..de90a7f --- /dev/null +++ b/tests/php/fpm/mysqli.php @@ -0,0 +1,35 @@ +query("SELECT 1"); + Assert::notFalse($result); +} + +{ + $mysqli = new mysqli("127.0.0.1", "root", "password", "skywalking", 3306); + $result = $mysqli->query("SELECT * FROM `mysql`.`user` WHERE `User` = 'root'"); + $rs = $result->fetch_all(); + Assert::same(count($rs), 2); +} + +echo "ok"; diff --git a/tests/php/fpm/pdo.php b/tests/php/fpm/pdo.php new file mode 100644 index 0000000..ac2ebe1 --- /dev/null +++ b/tests/php/fpm/pdo.php @@ -0,0 +1,53 @@ +exec("SELECT 1"); + Assert::notFalse($result); +} + +{ + $pdo = new PDO("mysql:dbname=skywalking;host=127.0.0.1:3306", "root", "password"); + $sth = $pdo->prepare("SELECT * FROM `mysql`.`user` WHERE `User` = :user", [PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY]); + $sth->execute(['user' => 'root']); + $rs = $sth->fetchAll(); + Assert::same(count($rs), 2); +} + +{ + $pdo = new PDO("mysql:dbname=skywalking;host=127.0.0.1:3306;", "root", "password"); + $sth = $pdo->prepare("SELECT * FROM `mysql`.`user` WHERE `User` = :user", [PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY]); + $sth->execute(['user' => 'anon']); + $rs = $sth->fetchAll(); + Assert::same(count($rs), 0); +} + +{ + Assert::throws(function () { + $pdo = new PDO("mysql:dbname=skywalking;host=127.0.0.1;port=3306", "root", "password"); + $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $sth = $pdo->prepare("SELECT * FROM not_exist"); + $sth->execute(); + }, PDOException::class); +} + +echo "ok"; diff --git a/tests/php/fpm/predis.php b/tests/php/fpm/predis.php new file mode 100644 index 0000000..98375b5 --- /dev/null +++ b/tests/php/fpm/predis.php @@ -0,0 +1,32 @@ +auth('password'); + $client->set('foo', 'bar'); + $value = $client->get('foo'); + Assert::same($value, 'bar'); + $client->get('not-exists'); +} + +echo "ok"; diff --git a/tests/php/fpm/rabbitmq.php b/tests/php/fpm/rabbitmq.php new file mode 100644 index 0000000..162f8bd --- /dev/null +++ b/tests/php/fpm/rabbitmq.php @@ -0,0 +1,49 @@ +channel(); + +$channel->queue_declare('queue_test', false, false, false, false); +$channel->exchange_declare('exchange_test', 'direct', false, false, false); +$channel->queue_bind('queue_test', 'exchange_test', 'routing_test'); + +{ + $msg = new AMQPMessage('Hello World!'); + $channel->basic_publish($msg, '', 'queue_test'); +} + +{ + $msg = new AMQPMessage('Hello World!', ['content_type' => 'text/plain']); + $channel->basic_publish($msg, 'exchange_test', 'routing_test'); +} + +{ + $msg = new AMQPMessage('Hello World!'); + $msg->set('application_headers', new AMQPTable(['foo' => 'bar'])); + $channel->basic_publish($msg, '', 'not_exists'); +} + +echo "ok"; diff --git a/tests/php/fpm/redis.fail.php b/tests/php/fpm/redis.fail.php new file mode 100644 index 0000000..be6610f --- /dev/null +++ b/tests/php/fpm/redis.fail.php @@ -0,0 +1,30 @@ +connect("127.0.0.1", 6379); + $client->set('foo', 'bar'); +} catch (RedisException $e) { +} + +echo "ok"; diff --git a/tests/php/fpm/redis.succ.php b/tests/php/fpm/redis.succ.php new file mode 100644 index 0000000..1abc743 --- /dev/null +++ b/tests/php/fpm/redis.succ.php @@ -0,0 +1,32 @@ +connect("127.0.0.1", 6379); + $client->auth('password'); + $client->mSet(['key0' => 'value0', 'key1' => 'value1']); + Assert::same($client->get('key0'), 'value0'); + Assert::same($client->get('key1'), 'value1'); +} + +echo "ok"; diff --git a/tests/php/swoole/main.1.php b/tests/php/swoole/main.1.php new file mode 100644 index 0000000..e70c685 --- /dev/null +++ b/tests/php/swoole/main.1.php @@ -0,0 +1,82 @@ +set([ + 'reactor_num' => 3, + 'worker_num' => 3, + 'enable_coroutine' => true, + 'hook_flags' => 0, +]); + +$http->on('start', function ($server) { + echo "Swoole http server is started at http://127.0.0.1:9501\n"; +}); + +$http->on('request', function ($request, $response) { + try { + switch ($request->server['request_uri']) { + case "/": + break; + + case "/curl": + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, "http://127.0.0.1:9501/?swoole=1"); + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HEADER, 0); + $output = curl_exec($ch); + curl_close($ch); + Assert::same($output, "ok"); + } + + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, "http://127.0.0.1:9502/"); + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HEADER, 0); + $output = curl_exec($ch); + curl_close($ch); + Assert::same($output, "ok"); + } + + break; + + default: + throw new DomainException("Unknown operation"); + } + + $response->header('Content-Type', 'text/plain'); + $response->end('ok'); + + } catch (Exception $e) { + $response->status(500); + $response->header('Content-Type', 'text/plain'); + $response->end($e->getMessage() . "\n" . $e->getTraceAsString()); + } +}); + +$http->start(); diff --git a/tests/php/swoole/main.2.php b/tests/php/swoole/main.2.php new file mode 100644 index 0000000..47cfcc0 --- /dev/null +++ b/tests/php/swoole/main.2.php @@ -0,0 +1,115 @@ +set([ + 'reactor_num' => 3, + 'worker_num' => 3, + 'enable_coroutine' => true, + 'hook_flags' => SWOOLE_HOOK_ALL, +]); + +$http->on('start', function ($server) { + echo "Swoole http server is started at http://127.0.0.1:9502\n"; +}); + +$http->on('request', function ($request, $response) { + try { + switch ($request->server['request_uri']) { + case "/": + break; + + case '/curl': + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, "http://127.0.0.1:9502/?swoole=2"); + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HEADER, 0); + $output = curl_exec($ch); + curl_close($ch); + Assert::same($output, "ok"); + } + break; + + case '/pdo': + { + $pdo = new PDO("mysql:dbname=skywalking;host=127.0.0.1;port=3306", "root", "password"); + $result = $pdo->exec("SELECT 1"); + Assert::notFalse($result); + } + break; + + case '/mysqli': + { + $mysqli = new mysqli("127.0.0.1", "root", "password", "skywalking", 3306); + $result = $mysqli->query("SELECT 1"); + Assert::notFalse($result); + } + break; + + case '/memcached': + { + $mc = new Memcached(); + $mc->addServer("127.0.0.1", 11211); + + $mc->set("foo000", "bar000"); + Assert::same($mc->get("foo000"), 'bar000'); + } + break; + + case '/redis': + { + $client = new Redis(); + $client->connect("127.0.0.1", 6379); + $client->auth('password'); + $client->set('foo001', 'bar001'); + Assert::same($client->get('foo001'), 'bar001'); + } + break; + + case '/predis': + { + $client = new Predis\Client(); + $client->auth('password'); + $client->set('foo002', 'bar002'); + Assert::same($client->get('foo002'), 'bar002'); + } + break; + + default: + throw new DomainException("Unknown operation"); + } + + $response->header('Content-Type', 'text/plain'); + $response->end('ok'); + + } catch (Exception $e) { + $response->status(500); + $response->header('Content-Type', 'text/plain'); + $response->end($e->getMessage() . "\n" . $e->getTraceAsString()); + } +}); + +$http->start();