This is an automated email from the ASF dual-hosted git repository.
kezhenxu94 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking-python.git
The following commit(s) were added to refs/heads/master by this push:
new 320ef70 feat: add sw_grpc plugin (#362)
320ef70 is described below
commit 320ef706ddeb1cbf6230bb5adf153ed71ad211a6
Author: Tsonglew <[email protected]>
AuthorDate: Mon Nov 18 10:16:40 2024 +0800
feat: add sw_grpc plugin (#362)
---
CHANGELOG.md | 3 +
docs/en/setup/Configuration.md | 1 +
docs/en/setup/Plugins.md | 1 +
poetry.lock | 366 ++++++++--------
pyproject.toml | 1 +
skywalking/__init__.py | 3 +-
skywalking/config.py | 11 +-
skywalking/meter/pvm/data_source.py | 2 +-
skywalking/plugins/sw_grpc.py | 477 +++++++++++++++++++++
skywalking/trace/context.py | 2 +-
skywalking/trace/tags.py | 13 +
.../plugin/web/sw_grpc/__init__.py | 10 -
tests/plugin/web/sw_grpc/docker-compose.yml | 114 +++++
tests/plugin/web/sw_grpc/example.proto | 41 ++
tests/plugin/web/sw_grpc/expected.data.yml | 384 +++++++++++++++++
.../plugin/web/sw_grpc/services/__init__.py | 10 -
tests/plugin/web/sw_grpc/services/aio_consumer.py | 54 +++
tests/plugin/web/sw_grpc/services/aio_provider.py | 66 +++
tests/plugin/web/sw_grpc/services/consumer.py | 50 +++
tests/plugin/web/sw_grpc/services/provider.py | 57 +++
.../plugin/web/sw_grpc/test_grpc.py | 31 +-
tools/config_doc_gen.py | 2 +-
22 files changed, 1484 insertions(+), 215 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a943610..190b400 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@
- Drop support for 3.7 (#356)
- Support sampling rate setup. Provide `SW_SAMPLE_N_PER_3_SECS` environment
variable to control it (#357)
+- Plugins:
+ - Add gRPC plugin (#362)
+
- Fixes:
- Fix: user/password replacement is not allowed for relative URLs (#349)
- Fix pulsar client does not support init arguments other than service_url
(#351)
diff --git a/docs/en/setup/Configuration.md b/docs/en/setup/Configuration.md
index c8c1658..42362d9 100644
--- a/docs/en/setup/Configuration.md
+++ b/docs/en/setup/Configuration.md
@@ -97,6 +97,7 @@ export SW_AGENT_YourConfiguration=YourValue
| plugin_fastapi_collect_http_params | SW_PLUGIN_FASTAPI_COLLECT_HTTP_PARAMS |
<class 'bool'> | False | This config item controls that whether the FastAPI
plugin should collect the parameters of the request. |
| plugin_bottle_collect_http_params | SW_PLUGIN_BOTTLE_COLLECT_HTTP_PARAMS |
<class 'bool'> | False | This config item controls that whether the Bottle
plugin should collect the parameters of the request. |
| plugin_celery_parameters_length | SW_PLUGIN_CELERY_PARAMETERS_LENGTH |
<class 'int'> | 512 | The maximum length of `celery` functions parameters,
longer than this will be truncated, 0 turns off |
+| plugin_grpc_ignored_methods | SW_PLUGIN_GRPC_IGNORED_METHODS | <class 'str'>
| | Comma-delimited list of user-defined grpc methods to ignore, like
/package.Service/Method1,/package.Service/Method2 |
### Sampling Configurations
| Configuration | Environment Variable | Type | Default Value | Description |
| :------------ | :------------ | :------------ | :------------ |
:------------ |
diff --git a/docs/en/setup/Plugins.md b/docs/en/setup/Plugins.md
index 4cb5891..af4c017 100644
--- a/docs/en/setup/Plugins.md
+++ b/docs/en/setup/Plugins.md
@@ -26,6 +26,7 @@ or a limitation of SkyWalking auto-instrumentation (welcome
to contribute!)
| [hug](https://falcon.readthedocs.io/en/stable/) | Python >=3.11 - NOT
SUPPORTED YET; Python >=3.10 - ['2.5', '2.6']; Python >=3.7 - ['2.4.1', '2.5',
'2.6']; | `sw_falcon` |
| [fastapi](https://fastapi.tiangolo.com) | Python >=3.7 - ['0.89.*',
'0.88.*']; | `sw_fastapi` |
| [flask](https://flask.palletsprojects.com) | Python >=3.7 - ['2.0']; |
`sw_flask` |
+| [grpcio](https://grpc.io/docs/languages/python) | Python >=3.8 - ['1.*']; |
`sw_grpc` |
| [happybase](https://happybase.readthedocs.io) | Python >=3.7 - ['1.2.0']; |
`sw_happybase` |
| [http_server](https://docs.python.org/3/library/http.server.html) | Python
>=3.7 - ['*']; | `sw_http_server` |
| [werkzeug](https://werkzeug.palletsprojects.com/) | Python >=3.7 - ['1.0.1',
'2.0']; | `sw_http_server` |
diff --git a/poetry.lock b/poetry.lock
index 32b03ff..01a14b4 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -149,13 +149,13 @@ yarl = "*"
[[package]]
name = "amqp"
-version = "5.2.0"
+version = "5.3.1"
description = "Low-level AMQP client for Python (fork of amqplib)."
optional = false
python-versions = ">=3.6"
files = [
- {file = "amqp-5.2.0-py3-none-any.whl", hash =
"sha256:827cb12fb0baa892aad844fd95258143bce4027fdac4fccddbc43330fd281637"},
- {file = "amqp-5.2.0.tar.gz", hash =
"sha256:a1ecff425ad063ad42a486c902807d1482311481c8ad95a72694b2975e75f7fd"},
+ {file = "amqp-5.3.1-py3-none-any.whl", hash =
"sha256:43b3319e1b4e7d1251833a93d672b4af1e40f3d632d479b98661a95f117880a2"},
+ {file = "amqp-5.3.1.tar.gz", hash =
"sha256:cddc00c725449522023bad949f70fff7b48f0b1ade74d170a6f10ab044739432"},
]
[package.dependencies]
@@ -1329,137 +1329,137 @@ test = ["objgraph", "psutil"]
[[package]]
name = "grpcio"
-version = "1.67.1"
+version = "1.68.0"
description = "HTTP/2-based RPC framework"
optional = false
python-versions = ">=3.8"
files = [
- {file = "grpcio-1.67.1-cp310-cp310-linux_armv7l.whl", hash =
"sha256:8b0341d66a57f8a3119b77ab32207072be60c9bf79760fa609c5609f2deb1f3f"},
- {file = "grpcio-1.67.1-cp310-cp310-macosx_12_0_universal2.whl", hash =
"sha256:f5a27dddefe0e2357d3e617b9079b4bfdc91341a91565111a21ed6ebbc51b22d"},
- {file = "grpcio-1.67.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash =
"sha256:43112046864317498a33bdc4797ae6a268c36345a910de9b9c17159d8346602f"},
- {file =
"grpcio-1.67.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash =
"sha256:c9b929f13677b10f63124c1a410994a401cdd85214ad83ab67cc077fc7e480f0"},
- {file =
"grpcio-1.67.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:e7d1797a8a3845437d327145959a2c0c47c05947c9eef5ff1a4c80e499dcc6fa"},
- {file = "grpcio-1.67.1-cp310-cp310-musllinux_1_1_i686.whl", hash =
"sha256:0489063974d1452436139501bf6b180f63d4977223ee87488fe36858c5725292"},
- {file = "grpcio-1.67.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash =
"sha256:9fd042de4a82e3e7aca44008ee2fb5da01b3e5adb316348c21980f7f58adc311"},
- {file = "grpcio-1.67.1-cp310-cp310-win32.whl", hash =
"sha256:638354e698fd0c6c76b04540a850bf1db27b4d2515a19fcd5cf645c48d3eb1ed"},
- {file = "grpcio-1.67.1-cp310-cp310-win_amd64.whl", hash =
"sha256:608d87d1bdabf9e2868b12338cd38a79969eaf920c89d698ead08f48de9c0f9e"},
- {file = "grpcio-1.67.1-cp311-cp311-linux_armv7l.whl", hash =
"sha256:7818c0454027ae3384235a65210bbf5464bd715450e30a3d40385453a85a70cb"},
- {file = "grpcio-1.67.1-cp311-cp311-macosx_10_9_universal2.whl", hash =
"sha256:ea33986b70f83844cd00814cee4451055cd8cab36f00ac64a31f5bb09b31919e"},
- {file = "grpcio-1.67.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash =
"sha256:c7a01337407dd89005527623a4a72c5c8e2894d22bead0895306b23c6695698f"},
- {file =
"grpcio-1.67.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash =
"sha256:80b866f73224b0634f4312a4674c1be21b2b4afa73cb20953cbbb73a6b36c3cc"},
- {file =
"grpcio-1.67.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:f9fff78ba10d4250bfc07a01bd6254a6d87dc67f9627adece85c0b2ed754fa96"},
- {file = "grpcio-1.67.1-cp311-cp311-musllinux_1_1_i686.whl", hash =
"sha256:8a23cbcc5bb11ea7dc6163078be36c065db68d915c24f5faa4f872c573bb400f"},
- {file = "grpcio-1.67.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash =
"sha256:1a65b503d008f066e994f34f456e0647e5ceb34cfcec5ad180b1b44020ad4970"},
- {file = "grpcio-1.67.1-cp311-cp311-win32.whl", hash =
"sha256:e29ca27bec8e163dca0c98084040edec3bc49afd10f18b412f483cc68c712744"},
- {file = "grpcio-1.67.1-cp311-cp311-win_amd64.whl", hash =
"sha256:786a5b18544622bfb1e25cc08402bd44ea83edfb04b93798d85dca4d1a0b5be5"},
- {file = "grpcio-1.67.1-cp312-cp312-linux_armv7l.whl", hash =
"sha256:267d1745894200e4c604958da5f856da6293f063327cb049a51fe67348e4f953"},
- {file = "grpcio-1.67.1-cp312-cp312-macosx_10_9_universal2.whl", hash =
"sha256:85f69fdc1d28ce7cff8de3f9c67db2b0ca9ba4449644488c1e0303c146135ddb"},
- {file = "grpcio-1.67.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash =
"sha256:f26b0b547eb8d00e195274cdfc63ce64c8fc2d3e2d00b12bf468ece41a0423a0"},
- {file =
"grpcio-1.67.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash =
"sha256:4422581cdc628f77302270ff839a44f4c24fdc57887dc2a45b7e53d8fc2376af"},
- {file =
"grpcio-1.67.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:1d7616d2ded471231c701489190379e0c311ee0a6c756f3c03e6a62b95a7146e"},
- {file = "grpcio-1.67.1-cp312-cp312-musllinux_1_1_i686.whl", hash =
"sha256:8a00efecde9d6fcc3ab00c13f816313c040a28450e5e25739c24f432fc6d3c75"},
- {file = "grpcio-1.67.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash =
"sha256:699e964923b70f3101393710793289e42845791ea07565654ada0969522d0a38"},
- {file = "grpcio-1.67.1-cp312-cp312-win32.whl", hash =
"sha256:4e7b904484a634a0fff132958dabdb10d63e0927398273917da3ee103e8d1f78"},
- {file = "grpcio-1.67.1-cp312-cp312-win_amd64.whl", hash =
"sha256:5721e66a594a6c4204458004852719b38f3d5522082be9061d6510b455c90afc"},
- {file = "grpcio-1.67.1-cp313-cp313-linux_armv7l.whl", hash =
"sha256:aa0162e56fd10a5547fac8774c4899fc3e18c1aa4a4759d0ce2cd00d3696ea6b"},
- {file = "grpcio-1.67.1-cp313-cp313-macosx_10_13_universal2.whl", hash =
"sha256:beee96c8c0b1a75d556fe57b92b58b4347c77a65781ee2ac749d550f2a365dc1"},
- {file = "grpcio-1.67.1-cp313-cp313-manylinux_2_17_aarch64.whl", hash =
"sha256:a93deda571a1bf94ec1f6fcda2872dad3ae538700d94dc283c672a3b508ba3af"},
- {file =
"grpcio-1.67.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash =
"sha256:0e6f255980afef598a9e64a24efce87b625e3e3c80a45162d111a461a9f92955"},
- {file =
"grpcio-1.67.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:9e838cad2176ebd5d4a8bb03955138d6589ce9e2ce5d51c3ada34396dbd2dba8"},
- {file = "grpcio-1.67.1-cp313-cp313-musllinux_1_1_i686.whl", hash =
"sha256:a6703916c43b1d468d0756c8077b12017a9fcb6a1ef13faf49e67d20d7ebda62"},
- {file = "grpcio-1.67.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash =
"sha256:917e8d8994eed1d86b907ba2a61b9f0aef27a2155bca6cbb322430fc7135b7bb"},
- {file = "grpcio-1.67.1-cp313-cp313-win32.whl", hash =
"sha256:e279330bef1744040db8fc432becc8a727b84f456ab62b744d3fdb83f327e121"},
- {file = "grpcio-1.67.1-cp313-cp313-win_amd64.whl", hash =
"sha256:fa0c739ad8b1996bd24823950e3cb5152ae91fca1c09cc791190bf1627ffefba"},
- {file = "grpcio-1.67.1-cp38-cp38-linux_armv7l.whl", hash =
"sha256:178f5db771c4f9a9facb2ab37a434c46cb9be1a75e820f187ee3d1e7805c4f65"},
- {file = "grpcio-1.67.1-cp38-cp38-macosx_10_9_universal2.whl", hash =
"sha256:0f3e49c738396e93b7ba9016e153eb09e0778e776df6090c1b8c91877cc1c426"},
- {file = "grpcio-1.67.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash =
"sha256:24e8a26dbfc5274d7474c27759b54486b8de23c709d76695237515bc8b5baeab"},
- {file =
"grpcio-1.67.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash =
"sha256:3b6c16489326d79ead41689c4b84bc40d522c9a7617219f4ad94bc7f448c5085"},
- {file =
"grpcio-1.67.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash
= "sha256:60e6a4dcf5af7bbc36fd9f81c9f372e8ae580870a9e4b6eafe948cd334b81cf3"},
- {file = "grpcio-1.67.1-cp38-cp38-musllinux_1_1_i686.whl", hash =
"sha256:95b5f2b857856ed78d72da93cd7d09b6db8ef30102e5e7fe0961fe4d9f7d48e8"},
- {file = "grpcio-1.67.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash =
"sha256:b49359977c6ec9f5d0573ea4e0071ad278ef905aa74e420acc73fd28ce39e9ce"},
- {file = "grpcio-1.67.1-cp38-cp38-win32.whl", hash =
"sha256:f5b76ff64aaac53fede0cc93abf57894ab2a7362986ba22243d06218b93efe46"},
- {file = "grpcio-1.67.1-cp38-cp38-win_amd64.whl", hash =
"sha256:804c6457c3cd3ec04fe6006c739579b8d35c86ae3298ffca8de57b493524b771"},
- {file = "grpcio-1.67.1-cp39-cp39-linux_armv7l.whl", hash =
"sha256:a25bdea92b13ff4d7790962190bf6bf5c4639876e01c0f3dda70fc2769616335"},
- {file = "grpcio-1.67.1-cp39-cp39-macosx_10_9_universal2.whl", hash =
"sha256:cdc491ae35a13535fd9196acb5afe1af37c8237df2e54427be3eecda3653127e"},
- {file = "grpcio-1.67.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash =
"sha256:85f862069b86a305497e74d0dc43c02de3d1d184fc2c180993aa8aa86fbd19b8"},
- {file =
"grpcio-1.67.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash =
"sha256:ec74ef02010186185de82cc594058a3ccd8d86821842bbac9873fd4a2cf8be8d"},
- {file =
"grpcio-1.67.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash
= "sha256:01f616a964e540638af5130469451cf580ba8c7329f45ca998ab66e0c7dcdb04"},
- {file = "grpcio-1.67.1-cp39-cp39-musllinux_1_1_i686.whl", hash =
"sha256:299b3d8c4f790c6bcca485f9963b4846dd92cf6f1b65d3697145d005c80f9fe8"},
- {file = "grpcio-1.67.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash =
"sha256:60336bff760fbb47d7e86165408126f1dded184448e9a4c892189eb7c9d3f90f"},
- {file = "grpcio-1.67.1-cp39-cp39-win32.whl", hash =
"sha256:5ed601c4c6008429e3d247ddb367fe8c7259c355757448d7c1ef7bd4a6739e8e"},
- {file = "grpcio-1.67.1-cp39-cp39-win_amd64.whl", hash =
"sha256:5db70d32d6703b89912af16d6d45d78406374a8b8ef0d28140351dd0ec610e98"},
- {file = "grpcio-1.67.1.tar.gz", hash =
"sha256:3dc2ed4cabea4dc14d5e708c2b426205956077cc5de419b4d4079315017e9732"},
-]
-
-[package.extras]
-protobuf = ["grpcio-tools (>=1.67.1)"]
+ {file = "grpcio-1.68.0-cp310-cp310-linux_armv7l.whl", hash =
"sha256:619b5d0f29f4f5351440e9343224c3e19912c21aeda44e0c49d0d147a8d01544"},
+ {file = "grpcio-1.68.0-cp310-cp310-macosx_12_0_universal2.whl", hash =
"sha256:a59f5822f9459bed098ffbceb2713abbf7c6fd13f2b9243461da5c338d0cd6c3"},
+ {file = "grpcio-1.68.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash =
"sha256:c03d89df516128febc5a7e760d675b478ba25802447624edf7aa13b1e7b11e2a"},
+ {file =
"grpcio-1.68.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash =
"sha256:44bcbebb24363d587472089b89e2ea0ab2e2b4df0e4856ba4c0b087c82412121"},
+ {file =
"grpcio-1.68.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:79f81b7fbfb136247b70465bd836fa1733043fdee539cd6031cb499e9608a110"},
+ {file = "grpcio-1.68.0-cp310-cp310-musllinux_1_1_i686.whl", hash =
"sha256:88fb2925789cfe6daa20900260ef0a1d0a61283dfb2d2fffe6194396a354c618"},
+ {file = "grpcio-1.68.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash =
"sha256:99f06232b5c9138593ae6f2e355054318717d32a9c09cdc5a2885540835067a1"},
+ {file = "grpcio-1.68.0-cp310-cp310-win32.whl", hash =
"sha256:a6213d2f7a22c3c30a479fb5e249b6b7e648e17f364598ff64d08a5136fe488b"},
+ {file = "grpcio-1.68.0-cp310-cp310-win_amd64.whl", hash =
"sha256:15327ab81131ef9b94cb9f45b5bd98803a179c7c61205c8c0ac9aff9d6c4e82a"},
+ {file = "grpcio-1.68.0-cp311-cp311-linux_armv7l.whl", hash =
"sha256:3b2b559beb2d433129441783e5f42e3be40a9e1a89ec906efabf26591c5cd415"},
+ {file = "grpcio-1.68.0-cp311-cp311-macosx_10_9_universal2.whl", hash =
"sha256:e46541de8425a4d6829ac6c5d9b16c03c292105fe9ebf78cb1c31e8d242f9155"},
+ {file = "grpcio-1.68.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash =
"sha256:c1245651f3c9ea92a2db4f95d37b7597db6b246d5892bca6ee8c0e90d76fb73c"},
+ {file =
"grpcio-1.68.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash =
"sha256:4f1931c7aa85be0fa6cea6af388e576f3bf6baee9e5d481c586980c774debcb4"},
+ {file =
"grpcio-1.68.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:8b0ff09c81e3aded7a183bc6473639b46b6caa9c1901d6f5e2cba24b95e59e30"},
+ {file = "grpcio-1.68.0-cp311-cp311-musllinux_1_1_i686.whl", hash =
"sha256:8c73f9fbbaee1a132487e31585aa83987ddf626426d703ebcb9a528cf231c9b1"},
+ {file = "grpcio-1.68.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash =
"sha256:6b2f98165ea2790ea159393a2246b56f580d24d7da0d0342c18a085299c40a75"},
+ {file = "grpcio-1.68.0-cp311-cp311-win32.whl", hash =
"sha256:e1e7ed311afb351ff0d0e583a66fcb39675be112d61e7cfd6c8269884a98afbc"},
+ {file = "grpcio-1.68.0-cp311-cp311-win_amd64.whl", hash =
"sha256:e0d2f68eaa0a755edd9a47d40e50dba6df2bceda66960dee1218da81a2834d27"},
+ {file = "grpcio-1.68.0-cp312-cp312-linux_armv7l.whl", hash =
"sha256:8af6137cc4ae8e421690d276e7627cfc726d4293f6607acf9ea7260bd8fc3d7d"},
+ {file = "grpcio-1.68.0-cp312-cp312-macosx_10_9_universal2.whl", hash =
"sha256:4028b8e9a3bff6f377698587d642e24bd221810c06579a18420a17688e421af7"},
+ {file = "grpcio-1.68.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash =
"sha256:f60fa2adf281fd73ae3a50677572521edca34ba373a45b457b5ebe87c2d01e1d"},
+ {file =
"grpcio-1.68.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash =
"sha256:e18589e747c1e70b60fab6767ff99b2d0c359ea1db8a2cb524477f93cdbedf5b"},
+ {file =
"grpcio-1.68.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:e0d30f3fee9372796f54d3100b31ee70972eaadcc87314be369360248a3dcffe"},
+ {file = "grpcio-1.68.0-cp312-cp312-musllinux_1_1_i686.whl", hash =
"sha256:7e0a3e72c0e9a1acab77bef14a73a416630b7fd2cbd893c0a873edc47c42c8cd"},
+ {file = "grpcio-1.68.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash =
"sha256:a831dcc343440969aaa812004685ed322cdb526cd197112d0db303b0da1e8659"},
+ {file = "grpcio-1.68.0-cp312-cp312-win32.whl", hash =
"sha256:5a180328e92b9a0050958ced34dddcb86fec5a8b332f5a229e353dafc16cd332"},
+ {file = "grpcio-1.68.0-cp312-cp312-win_amd64.whl", hash =
"sha256:2bddd04a790b69f7a7385f6a112f46ea0b34c4746f361ebafe9ca0be567c78e9"},
+ {file = "grpcio-1.68.0-cp313-cp313-linux_armv7l.whl", hash =
"sha256:fc05759ffbd7875e0ff2bd877be1438dfe97c9312bbc558c8284a9afa1d0f40e"},
+ {file = "grpcio-1.68.0-cp313-cp313-macosx_10_13_universal2.whl", hash =
"sha256:15fa1fe25d365a13bc6d52fcac0e3ee1f9baebdde2c9b3b2425f8a4979fccea1"},
+ {file = "grpcio-1.68.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash =
"sha256:32a9cb4686eb2e89d97022ecb9e1606d132f85c444354c17a7dbde4a455e4a3b"},
+ {file =
"grpcio-1.68.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash =
"sha256:dba037ff8d284c8e7ea9a510c8ae0f5b016004f13c3648f72411c464b67ff2fb"},
+ {file =
"grpcio-1.68.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:0efbbd849867e0e569af09e165363ade75cf84f5229b2698d53cf22c7a4f9e21"},
+ {file = "grpcio-1.68.0-cp313-cp313-musllinux_1_1_i686.whl", hash =
"sha256:4e300e6978df0b65cc2d100c54e097c10dfc7018b9bd890bbbf08022d47f766d"},
+ {file = "grpcio-1.68.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash =
"sha256:6f9c7ad1a23e1047f827385f4713b5b8c6c7d325705be1dd3e31fb00dcb2f665"},
+ {file = "grpcio-1.68.0-cp313-cp313-win32.whl", hash =
"sha256:3ac7f10850fd0487fcce169c3c55509101c3bde2a3b454869639df2176b60a03"},
+ {file = "grpcio-1.68.0-cp313-cp313-win_amd64.whl", hash =
"sha256:afbf45a62ba85a720491bfe9b2642f8761ff348006f5ef67e4622621f116b04a"},
+ {file = "grpcio-1.68.0-cp38-cp38-linux_armv7l.whl", hash =
"sha256:f8f695d9576ce836eab27ba7401c60acaf9ef6cf2f70dfe5462055ba3df02cc3"},
+ {file = "grpcio-1.68.0-cp38-cp38-macosx_10_9_universal2.whl", hash =
"sha256:9fe1b141cda52f2ca73e17d2d3c6a9f3f3a0c255c216b50ce616e9dca7e3441d"},
+ {file = "grpcio-1.68.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash =
"sha256:4df81d78fd1646bf94ced4fb4cd0a7fe2e91608089c522ef17bc7db26e64effd"},
+ {file =
"grpcio-1.68.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash =
"sha256:46a2d74d4dd8993151c6cd585594c082abe74112c8e4175ddda4106f2ceb022f"},
+ {file =
"grpcio-1.68.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash
= "sha256:a17278d977746472698460c63abf333e1d806bd41f2224f90dbe9460101c9796"},
+ {file = "grpcio-1.68.0-cp38-cp38-musllinux_1_1_i686.whl", hash =
"sha256:15377bce516b1c861c35e18eaa1c280692bf563264836cece693c0f169b48829"},
+ {file = "grpcio-1.68.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash =
"sha256:cc5f0a4f5904b8c25729a0498886b797feb817d1fd3812554ffa39551112c161"},
+ {file = "grpcio-1.68.0-cp38-cp38-win32.whl", hash =
"sha256:def1a60a111d24376e4b753db39705adbe9483ef4ca4761f825639d884d5da78"},
+ {file = "grpcio-1.68.0-cp38-cp38-win_amd64.whl", hash =
"sha256:55d3b52fd41ec5772a953612db4e70ae741a6d6ed640c4c89a64f017a1ac02b5"},
+ {file = "grpcio-1.68.0-cp39-cp39-linux_armv7l.whl", hash =
"sha256:0d230852ba97654453d290e98d6aa61cb48fa5fafb474fb4c4298d8721809354"},
+ {file = "grpcio-1.68.0-cp39-cp39-macosx_10_9_universal2.whl", hash =
"sha256:50992f214264e207e07222703c17d9cfdcc2c46ed5a1ea86843d440148ebbe10"},
+ {file = "grpcio-1.68.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash =
"sha256:14331e5c27ed3545360464a139ed279aa09db088f6e9502e95ad4bfa852bb116"},
+ {file =
"grpcio-1.68.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash =
"sha256:f84890b205692ea813653ece4ac9afa2139eae136e419231b0eec7c39fdbe4c2"},
+ {file =
"grpcio-1.68.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash
= "sha256:b0cf343c6f4f6aa44863e13ec9ddfe299e0be68f87d68e777328bff785897b05"},
+ {file = "grpcio-1.68.0-cp39-cp39-musllinux_1_1_i686.whl", hash =
"sha256:fd2c2d47969daa0e27eadaf15c13b5e92605c5e5953d23c06d0b5239a2f176d3"},
+ {file = "grpcio-1.68.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash =
"sha256:18668e36e7f4045820f069997834e94e8275910b1f03e078a6020bd464cb2363"},
+ {file = "grpcio-1.68.0-cp39-cp39-win32.whl", hash =
"sha256:2af76ab7c427aaa26aa9187c3e3c42f38d3771f91a20f99657d992afada2294a"},
+ {file = "grpcio-1.68.0-cp39-cp39-win_amd64.whl", hash =
"sha256:e694b5928b7b33ca2d3b4d5f9bf8b5888906f181daff6b406f4938f3a997a490"},
+ {file = "grpcio-1.68.0.tar.gz", hash =
"sha256:7e7483d39b4a4fddb9906671e9ea21aaad4f031cdfc349fec76bdfa1e404543a"},
+]
+
+[package.extras]
+protobuf = ["grpcio-tools (>=1.68.0)"]
[[package]]
name = "grpcio-tools"
-version = "1.67.1"
+version = "1.68.0"
description = "Protobuf code generator for gRPC"
optional = false
python-versions = ">=3.8"
files = [
- {file = "grpcio_tools-1.67.1-cp310-cp310-linux_armv7l.whl", hash =
"sha256:c701aaa51fde1f2644bd94941aa94c337adb86f25cd03cf05e37387aaea25800"},
- {file = "grpcio_tools-1.67.1-cp310-cp310-macosx_12_0_universal2.whl", hash
= "sha256:6a722bba714392de2386569c40942566b83725fa5c5450b8910e3832a5379469"},
- {file = "grpcio_tools-1.67.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash
= "sha256:0c7415235cb154e40b5ae90e2a172a0eb8c774b6876f53947cf0af05c983d549"},
- {file =
"grpcio_tools-1.67.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:6a4c459098c4934f9470280baf9ff8b38c365e147f33c8abc26039a948a664a5"},
- {file =
"grpcio_tools-1.67.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:e89bf53a268f55c16989dab1cf0b32a5bff910762f138136ffad4146129b7a10"},
- {file = "grpcio_tools-1.67.1-cp310-cp310-musllinux_1_1_i686.whl", hash =
"sha256:f09cb3e6bcb140f57b878580cf3b848976f67faaf53d850a7da9bfac12437068"},
- {file = "grpcio_tools-1.67.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash =
"sha256:616dd0c6686212ca90ff899bb37eb774798677e43dc6f78c6954470782d37399"},
- {file = "grpcio_tools-1.67.1-cp310-cp310-win32.whl", hash =
"sha256:58a66dbb3f0fef0396737ac09d6571a7f8d96a544ce3ed04c161f3d4fa8d51cc"},
- {file = "grpcio_tools-1.67.1-cp310-cp310-win_amd64.whl", hash =
"sha256:89ee7c505bdf152e67c2cced6055aed4c2d4170f53a2b46a7e543d3b90e7b977"},
- {file = "grpcio_tools-1.67.1-cp311-cp311-linux_armv7l.whl", hash =
"sha256:6d80ddd87a2fb7131d242f7d720222ef4f0f86f53ec87b0a6198c343d8e4a86e"},
- {file = "grpcio_tools-1.67.1-cp311-cp311-macosx_10_9_universal2.whl", hash
= "sha256:b655425b82df51f3bd9fd3ba1a6282d5c9ce1937709f059cb3d419b224532d89"},
- {file = "grpcio_tools-1.67.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash
= "sha256:250241e6f9d20d0910a46887dfcbf2ec9108efd3b48f3fb95bb42d50d09d03f8"},
- {file =
"grpcio_tools-1.67.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:6008f5a5add0b6f03082edb597acf20d5a9e4e7c55ea1edac8296c19e6a0ec8d"},
- {file =
"grpcio_tools-1.67.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:5eff9818c3831fa23735db1fa39aeff65e790044d0a312260a0c41ae29cc2d9e"},
- {file = "grpcio_tools-1.67.1-cp311-cp311-musllinux_1_1_i686.whl", hash =
"sha256:262ab7c40113f8c3c246e28e369661ddf616a351cb34169b8ba470c9a9c3b56f"},
- {file = "grpcio_tools-1.67.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash =
"sha256:1eebd8c746adf5786fa4c3056258c21cc470e1eca51d3ed23a7fb6a697fe4e81"},
- {file = "grpcio_tools-1.67.1-cp311-cp311-win32.whl", hash =
"sha256:3eff92fb8ca1dd55e3af0ef02236c648921fb7d0e8ca206b889585804b3659ae"},
- {file = "grpcio_tools-1.67.1-cp311-cp311-win_amd64.whl", hash =
"sha256:1ed18281ee17e5e0f9f6ce0c6eb3825ca9b5a0866fc1db2e17fab8aca28b8d9f"},
- {file = "grpcio_tools-1.67.1-cp312-cp312-linux_armv7l.whl", hash =
"sha256:bd5caef3a484e226d05a3f72b2d69af500dca972cf434bf6b08b150880166f0b"},
- {file = "grpcio_tools-1.67.1-cp312-cp312-macosx_10_9_universal2.whl", hash
= "sha256:48a2d63d1010e5b218e8e758ecb2a8d63c0c6016434e9f973df1c3558917020a"},
- {file = "grpcio_tools-1.67.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash
= "sha256:baa64a6aa009bffe86309e236c81b02cd4a88c1ebd66f2d92e84e9b97a9ae857"},
- {file =
"grpcio_tools-1.67.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:4ab318c40b5e3c097a159035fc3e4ecfbe9b3d2c9de189e55468b2c27639a6ab"},
- {file =
"grpcio_tools-1.67.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:50eba3e31f9ac1149463ad9182a37349850904f142cffbd957cd7f54ec320b8e"},
- {file = "grpcio_tools-1.67.1-cp312-cp312-musllinux_1_1_i686.whl", hash =
"sha256:de6fbc071ecc4fe6e354a7939202191c1f1abffe37fbce9b08e7e9a5b93eba3d"},
- {file = "grpcio_tools-1.67.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash =
"sha256:db9e87f6ea4b0ce99b2651203480585fd9e8dd0dd122a19e46836e93e3a1b749"},
- {file = "grpcio_tools-1.67.1-cp312-cp312-win32.whl", hash =
"sha256:6a595a872fb720dde924c4e8200f41d5418dd6baab8cc1a3c1e540f8f4596351"},
- {file = "grpcio_tools-1.67.1-cp312-cp312-win_amd64.whl", hash =
"sha256:92eebb9b31031604ae97ea7657ae2e43149b0394af7117ad7e15894b6cc136dc"},
- {file = "grpcio_tools-1.67.1-cp313-cp313-linux_armv7l.whl", hash =
"sha256:9a3b9510cc87b6458b05ad49a6dee38df6af37f9ee6aa027aa086537798c3d4a"},
- {file = "grpcio_tools-1.67.1-cp313-cp313-macosx_10_13_universal2.whl",
hash =
"sha256:9e4c9b9fa9b905f15d414cb7bd007ba7499f8907bdd21231ab287a86b27da81a"},
- {file = "grpcio_tools-1.67.1-cp313-cp313-manylinux_2_17_aarch64.whl", hash
= "sha256:e11a98b41af4bc88b7a738232b8fa0306ad82c79fa5d7090bb607f183a57856f"},
- {file =
"grpcio_tools-1.67.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:de0fcfe61c26679d64b1710746f2891f359593f76894fcf492c37148d5694f00"},
- {file =
"grpcio_tools-1.67.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:7ae3b3e2ee5aad59dece65a613624c46a84c9582fc3642686537c6dfae8e47dc"},
- {file = "grpcio_tools-1.67.1-cp313-cp313-musllinux_1_1_i686.whl", hash =
"sha256:9a630f83505b6471a3094a7a372a1240de18d0cd3e64f4fbf46b361bac2be65b"},
- {file = "grpcio_tools-1.67.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash =
"sha256:d85a1fcbacd3e08dc2b3d1d46b749351a9a50899fa35cf2ff040e1faf7d405ad"},
- {file = "grpcio_tools-1.67.1-cp313-cp313-win32.whl", hash =
"sha256:778470f025f25a1fca5a48c93c0a18af395b46b12dd8df7fca63736b85181f41"},
- {file = "grpcio_tools-1.67.1-cp313-cp313-win_amd64.whl", hash =
"sha256:6961da86e9856b4ddee0bf51ef6636b4bf9c29c0715aa71f3c8f027c45d42654"},
- {file = "grpcio_tools-1.67.1-cp38-cp38-linux_armv7l.whl", hash =
"sha256:c088dfbbe289bb171ca9c98fabbf7ecc8c1c51af2ba384ef32a4fdcb784b17e9"},
- {file = "grpcio_tools-1.67.1-cp38-cp38-macosx_10_9_universal2.whl", hash =
"sha256:11ce546daf8f8c04ee8d4a1673b4754cda4a0a9d505d820efd636e37f46b50c5"},
- {file = "grpcio_tools-1.67.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash =
"sha256:83fecb2f6119ef0eea68a091964898418c1969375d399956ff8d1741beb7b081"},
- {file =
"grpcio_tools-1.67.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:d39c1aa6b26e2602d815b9cfa37faba48b2889680ae6baa002560cf0f0c69fac"},
- {file =
"grpcio_tools-1.67.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:e975dc9fb61a77d88e739eb17b3361f369d03cc754217f02dd83ec7cfac32e38"},
- {file = "grpcio_tools-1.67.1-cp38-cp38-musllinux_1_1_i686.whl", hash =
"sha256:6c6e5c5b15f2eedc2a81268d588d14a79a52020383bf87b3c7595df7b571504a"},
- {file = "grpcio_tools-1.67.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash =
"sha256:a974e0ce01806adba718e6eb8c385defe6805b18969b6914da7db55fb055ae45"},
- {file = "grpcio_tools-1.67.1-cp38-cp38-win32.whl", hash =
"sha256:35e9b0a82be9f425aa67ee1dc69ba02cf135aeee3f22c0455c5d1b01769bbdb4"},
- {file = "grpcio_tools-1.67.1-cp38-cp38-win_amd64.whl", hash =
"sha256:0436c97f29e654d2eccd7419907ee019caf7eea6bdc6ae91d98011f6c5f44f17"},
- {file = "grpcio_tools-1.67.1-cp39-cp39-linux_armv7l.whl", hash =
"sha256:718fbb6d68a3d000cb3cf381642660eade0e8c1b0bf7472b84b3367f5b56171d"},
- {file = "grpcio_tools-1.67.1-cp39-cp39-macosx_10_9_universal2.whl", hash =
"sha256:062887d2e9cb8bc261c21a2b8da714092893ce62b4e072775eaa9b24dcbf3b31"},
- {file = "grpcio_tools-1.67.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash =
"sha256:59dbf14a1ce928bf03a58fa157034374411159ab5d32ad83cf146d9400eed618"},
- {file =
"grpcio_tools-1.67.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:ac552fc9c76d50408d7141e1fd1eae69d85fbf7ae71da4d8877eaa07127fbe74"},
- {file =
"grpcio_tools-1.67.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:5c6583773400e441dc62d08b5a32357babef1a9f9f73c3ac328a75af550815a9"},
- {file = "grpcio_tools-1.67.1-cp39-cp39-musllinux_1_1_i686.whl", hash =
"sha256:862108f90f2f6408908e5ea4584c5104f7caf419c6d73aa3ff36bf8284cca224"},
- {file = "grpcio_tools-1.67.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash =
"sha256:587c6326425f37dca2291f46b93e446c07ee781cea27725865b806b7a049ec56"},
- {file = "grpcio_tools-1.67.1-cp39-cp39-win32.whl", hash =
"sha256:d7d46a4405bd763525215b6e073888386587aef9b4a5ec125bf97ba897ac757d"},
- {file = "grpcio_tools-1.67.1-cp39-cp39-win_amd64.whl", hash =
"sha256:e2fc7980e8bab3ee5ab98b6fdc2a8fbaa4785f196d897531346176fda49a605c"},
- {file = "grpcio_tools-1.67.1.tar.gz", hash =
"sha256:d9657f5ddc62b52f58904e6054b7d8a8909ed08a1e28b734be3a707087bcf004"},
+ {file = "grpcio_tools-1.68.0-cp310-cp310-linux_armv7l.whl", hash =
"sha256:9509a5c3ed3d54fa7ac20748d501cb86668f764605a0a68f275339ee0f1dc1a6"},
+ {file = "grpcio_tools-1.68.0-cp310-cp310-macosx_12_0_universal2.whl", hash
= "sha256:59a885091bf29700ba0e14a954d156a18714caaa2006a7f328b18e1ac4b1e721"},
+ {file = "grpcio_tools-1.68.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash
= "sha256:d3e678162e1d7a8720dc05fdd537fc8df082a50831791f7bb1c6f90095f8368b"},
+ {file =
"grpcio_tools-1.68.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:10d03e3ad4af6284fd27cb14f5a3d52045913c1253e3e24a384ed91bc8adbfcd"},
+ {file =
"grpcio_tools-1.68.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:1769d7f529de1cc102f7fb900611e3c0b69bdb244fca1075b24d6e5b49024586"},
+ {file = "grpcio_tools-1.68.0-cp310-cp310-musllinux_1_1_i686.whl", hash =
"sha256:88640d95ee41921ac7352fa5fadca52a06d7e21fbe53e6a706a9a494f756be7d"},
+ {file = "grpcio_tools-1.68.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash =
"sha256:e903d07bc65232aa9e7704c829aec263e1e139442608e473d7912417a9908e29"},
+ {file = "grpcio_tools-1.68.0-cp310-cp310-win32.whl", hash =
"sha256:66b70b37184d40806844f51c2757c6b852511d4ea46a3bf2c7e931a47b455bc6"},
+ {file = "grpcio_tools-1.68.0-cp310-cp310-win_amd64.whl", hash =
"sha256:b47ae076ffb29a68e517bc03552bef0d9c973f8e18adadff180b123e973a26ea"},
+ {file = "grpcio_tools-1.68.0-cp311-cp311-linux_armv7l.whl", hash =
"sha256:f65942fab440e99113ce14436deace7554d5aa554ea18358e3a5f3fc47efe322"},
+ {file = "grpcio_tools-1.68.0-cp311-cp311-macosx_10_9_universal2.whl", hash
= "sha256:8fefc6d000e169a97336feded23ce614df3fb9926fc48c7a9ff8ea459d93b5b0"},
+ {file = "grpcio_tools-1.68.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash
= "sha256:6dd69c9f3ff85eee8d1f71adf7023c638ca8d465633244ac1b7f19bc3668612d"},
+ {file =
"grpcio_tools-1.68.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:7dc5195dc02057668cc22da1ff1aea1811f6fa0deb801b3194dec1fe0bab1cf0"},
+ {file =
"grpcio_tools-1.68.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:849b12bec2320e49e988df104c92217d533e01febac172a4495caab36d9f0edc"},
+ {file = "grpcio_tools-1.68.0-cp311-cp311-musllinux_1_1_i686.whl", hash =
"sha256:766c2cd2e365e0fc0e559af56f2c2d144d95fd7cb8668a34d533e66d6435eb34"},
+ {file = "grpcio_tools-1.68.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash =
"sha256:2ec3a2e0afa4866ccc5ba33c071aebaa619245dfdd840cbb74f2b0591868d085"},
+ {file = "grpcio_tools-1.68.0-cp311-cp311-win32.whl", hash =
"sha256:80b733014eb40d920d836d782e5cdea0dcc90d251a2ffb35ab378ef4f8a42c14"},
+ {file = "grpcio_tools-1.68.0-cp311-cp311-win_amd64.whl", hash =
"sha256:f95103e3e4e7fee7c6123bc9e4e925e07ad24d8d09d7c1c916fb6c8d1cb9e726"},
+ {file = "grpcio_tools-1.68.0-cp312-cp312-linux_armv7l.whl", hash =
"sha256:dd9a654af8536b3de8525bff72a245fef62d572eabf96ac946fe850e707cb27d"},
+ {file = "grpcio_tools-1.68.0-cp312-cp312-macosx_10_9_universal2.whl", hash
= "sha256:0f77957e3a0916a0dd18d57ce6b49d95fc9a5cfed92310f226339c0fda5394f6"},
+ {file = "grpcio_tools-1.68.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash
= "sha256:92a09afe64fe26696595de2036e10967876d26b12c894cc9160f00152cacebe7"},
+ {file =
"grpcio_tools-1.68.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:28ebdbad2ef16699d07400b65260240851049a75502eff69a59b127d3ab960f1"},
+ {file =
"grpcio_tools-1.68.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:5d3150d784d8050b10dcf5eb06e04fb90747a1547fed3a062a608d940fe57066"},
+ {file = "grpcio_tools-1.68.0-cp312-cp312-musllinux_1_1_i686.whl", hash =
"sha256:261d98fd635595de42aadee848f9af46da6654d63791c888891e94f66c5d0682"},
+ {file = "grpcio_tools-1.68.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash =
"sha256:061345c0079b9471f32230186ab01acb908ea0e577bc1699a8cf47acef8be4af"},
+ {file = "grpcio_tools-1.68.0-cp312-cp312-win32.whl", hash =
"sha256:533ce6791a5ba21e35d74c6c25caf4776f5692785a170c01ea1153783ad5af31"},
+ {file = "grpcio_tools-1.68.0-cp312-cp312-win_amd64.whl", hash =
"sha256:56842a0ce74b4b92eb62cd5ee00181b2d3acc58ba0c4fd20d15a5db51f891ba6"},
+ {file = "grpcio_tools-1.68.0-cp313-cp313-linux_armv7l.whl", hash =
"sha256:1117a81592542f0c36575082daa6413c57ca39188b18a4c50ec7332616f4b97e"},
+ {file = "grpcio_tools-1.68.0-cp313-cp313-macosx_10_13_universal2.whl",
hash =
"sha256:51e5a090849b30c99a2396d42140b8a3e558eff6cdfa12603f9582e2cd07724e"},
+ {file = "grpcio_tools-1.68.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash
= "sha256:4fe611d89a1836df8936f066d39c7eb03d4241806449ec45d4b8e1c843ae8011"},
+ {file =
"grpcio_tools-1.68.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:c10f3faa0cc4d89eb546f53b623837af23e86dc495d3b89510bcc0e0a6c0b8b2"},
+ {file =
"grpcio_tools-1.68.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:46b537480b8fd2195d988120a28467601a2a3de2e504043b89fb90318e1eb754"},
+ {file = "grpcio_tools-1.68.0-cp313-cp313-musllinux_1_1_i686.whl", hash =
"sha256:17d0c9004ea82b4213955a585401e80c30d4b37a1d4ace32ccdea8db4d3b7d43"},
+ {file = "grpcio_tools-1.68.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash =
"sha256:2919faae04fe47bad57fc9b578aeaab527da260e851f321a253b6b11862254a8"},
+ {file = "grpcio_tools-1.68.0-cp313-cp313-win32.whl", hash =
"sha256:ee86157ef899f58ba2fe1055cce0d33bd703e99aa6d5a0895581ac3969f06bfa"},
+ {file = "grpcio_tools-1.68.0-cp313-cp313-win_amd64.whl", hash =
"sha256:d0470ffc6a93c86cdda48edd428d22e2fef17d854788d60d0d5f291038873157"},
+ {file = "grpcio_tools-1.68.0-cp38-cp38-linux_armv7l.whl", hash =
"sha256:795f2cd76f68a12b0b5541b98187ba367dd69b49d359cf98b781ead742961370"},
+ {file = "grpcio_tools-1.68.0-cp38-cp38-macosx_10_9_universal2.whl", hash =
"sha256:57e29e78c33fb1b1d557fbe7650d722d1f2b0a9f53ea73beb8ea47e627b6000b"},
+ {file = "grpcio_tools-1.68.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash =
"sha256:700f171cd3293ee8d50cd43171562ff07b14fa8e49ee471cd91c6924c7da8644"},
+ {file =
"grpcio_tools-1.68.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:196cd8a3a5963a4c9e424314df9eb573b305e6f958fe6508d26580ce01e7aa56"},
+ {file =
"grpcio_tools-1.68.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:cad40c3164ee9cef62524dea509449ea581b17ea493178beef051bf79b5103ca"},
+ {file = "grpcio_tools-1.68.0-cp38-cp38-musllinux_1_1_i686.whl", hash =
"sha256:ab93fab49fa1e699e577ff5fbb99aba660164d710d4c33cfe0aa9d06f585539f"},
+ {file = "grpcio_tools-1.68.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash =
"sha256:511224a99726eb84db9ddb84dc8a75377c3eae797d835f99e80128ec618376d5"},
+ {file = "grpcio_tools-1.68.0-cp38-cp38-win32.whl", hash =
"sha256:b4ca81770cd729a9ea536d871aacedbde2b732bb9bb83c9d993d63f58502153d"},
+ {file = "grpcio_tools-1.68.0-cp38-cp38-win_amd64.whl", hash =
"sha256:6950725bf7a496f81d3ec3324334ffc9dbec743b510dd0e897f51f8627eeb6ac"},
+ {file = "grpcio_tools-1.68.0-cp39-cp39-linux_armv7l.whl", hash =
"sha256:01ace351a51d7ee120963a4612b1f00e964462ec548db20d17f8902e238592c8"},
+ {file = "grpcio_tools-1.68.0-cp39-cp39-macosx_10_9_universal2.whl", hash =
"sha256:5afd2f3f7257b52228a7808a2b4a765893d4d802d7a2377d9284853e67d045c6"},
+ {file = "grpcio_tools-1.68.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash =
"sha256:453ee3193d59c974c678d91f08786f43c25ef753651b0825dc3d008c31baf68d"},
+ {file =
"grpcio_tools-1.68.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:b094b22919b786ad73c20372ef5e546330e7cd2c6dc12293b7ed586975f35d38"},
+ {file =
"grpcio_tools-1.68.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:26335eea976dfc1ff5d90b19c309a9425bd53868112a0507ad20f297f2c21d3e"},
+ {file = "grpcio_tools-1.68.0-cp39-cp39-musllinux_1_1_i686.whl", hash =
"sha256:c77ecc5164bb413a613bdac9091dcc29d26834a2ac42fcd1afdfcda9e3003e68"},
+ {file = "grpcio_tools-1.68.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash =
"sha256:e31be6dc61496a59c1079b0a669f93dfcc2cdc4b1dbdc4374247cd09cee1329b"},
+ {file = "grpcio_tools-1.68.0-cp39-cp39-win32.whl", hash =
"sha256:3aa40958355920ae2846c6fb5cadac4f2c8e33234a2982fef8101da0990e3968"},
+ {file = "grpcio_tools-1.68.0-cp39-cp39-win_amd64.whl", hash =
"sha256:19bafb80948eda979b1b3a63c1567162d06249f43068a0e46a028a448e6f72d4"},
+ {file = "grpcio_tools-1.68.0.tar.gz", hash =
"sha256:737804ec2225dd4cc27e633b4ca0e963b0795161bf678285fab6586e917fd867"},
]
[package.dependencies]
-grpcio = ">=1.67.1"
+grpcio = ">=1.68.0"
protobuf = ">=5.26.1,<6.0dev"
setuptools = "*"
@@ -1980,19 +1980,19 @@ files = [
[[package]]
name = "mysqlclient"
-version = "2.2.5"
+version = "2.2.6"
description = "Python interface to MySQL"
optional = false
python-versions = ">=3.8"
files = [
- {file = "mysqlclient-2.2.5-cp310-cp310-win_amd64.whl", hash =
"sha256:b78438314199504c64f69e1e3521f2c9b419f19fcd85158b44c997b64409a6af"},
- {file = "mysqlclient-2.2.5-cp311-cp311-win_amd64.whl", hash =
"sha256:b54511648c1455b43ac28f8b4c1f732c5b0c343e87f7a3bd6fc9f9fe0f91934e"},
- {file = "mysqlclient-2.2.5-cp312-cp312-win_amd64.whl", hash =
"sha256:e871ede4261d0d42b8ed20a2459db411c7deafedd8e77b7e4ba760be4a6a752b"},
- {file = "mysqlclient-2.2.5-cp313-cp313-win_amd64.whl", hash =
"sha256:8012c633aab8c91ea8172ac479807135b171501b9cad1a7cd9b58c4dc8dcdab5"},
- {file = "mysqlclient-2.2.5-cp39-cp39-win_amd64.whl", hash =
"sha256:3f9625bea2b9bcde0ace76b32708762d44597491092c819fd1bff5b4e27f709b"},
- {file = "mysqlclient-2.2.5-pp310-pypy310_pp73-win_amd64.whl", hash =
"sha256:1d2e2ca0fe8405d8d6464edd01bf059951279e4bc27284d39341bd4737b2bc64"},
- {file = "mysqlclient-2.2.5-pp39-pypy39_pp73-win_amd64.whl", hash =
"sha256:aee14f1872114865679fcb09aac3772de4595fa7dcf2f83a4c7afee15e508854"},
- {file = "mysqlclient-2.2.5.tar.gz", hash =
"sha256:add8643c32f738014d252d2bdebb478623b04802e8396d5903905db36474d3ff"},
+ {file = "mysqlclient-2.2.6-cp310-cp310-win_amd64.whl", hash =
"sha256:e94a92858203d97fd584bdb6d7ee8c56f2590db8d77fd44215c0dcf5e739bc37"},
+ {file = "mysqlclient-2.2.6-cp311-cp311-win_amd64.whl", hash =
"sha256:43c5b30be0675080b9c815f457d73397f0442173e7be83d089b126835e2617ae"},
+ {file = "mysqlclient-2.2.6-cp312-cp312-win_amd64.whl", hash =
"sha256:e940b41d85dfd7b190fa47d52f525f878cfa203d4653bf6a35b271b3c3be125b"},
+ {file = "mysqlclient-2.2.6-cp313-cp313-win_amd64.whl", hash =
"sha256:794857bce4f9a1903a99786dd29ad7887f45a870b3d11585b8c51c4a753c4174"},
+ {file = "mysqlclient-2.2.6-cp39-cp39-win_amd64.whl", hash =
"sha256:b0a5cddf1d3488b254605041070086cac743401d876a659a72d706a0d89c8ebb"},
+ {file = "mysqlclient-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash =
"sha256:f3efb849d6f7ef4b9788a0eda2e896b975e0ebf1d6bf3dcabea63fd698e5b0b5"},
+ {file = "mysqlclient-2.2.6-pp39-pypy39_pp73-win_amd64.whl", hash =
"sha256:3da70a07753ba6be881f7d75e795e254f6a0c12795778034acc69769b0649d37"},
+ {file = "mysqlclient-2.2.6.tar.gz", hash =
"sha256:c0b46d9b78b461dbb62482089ca8040fa916595b1b30f831ebbd1b0a82b43d53"},
]
[[package]]
@@ -2016,13 +2016,13 @@ pyarrow = ["pyarrow (>=1.0.0)"]
[[package]]
name = "packaging"
-version = "24.1"
+version = "24.2"
description = "Core utilities for Python packages"
optional = false
python-versions = ">=3.8"
files = [
- {file = "packaging-24.1-py3-none-any.whl", hash =
"sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"},
- {file = "packaging-24.1.tar.gz", hash =
"sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
+ {file = "packaging-24.2-py3-none-any.whl", hash =
"sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"},
+ {file = "packaging-24.2.tar.gz", hash =
"sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"},
]
[[package]]
@@ -2598,54 +2598,54 @@ files = [
[[package]]
name = "pydantic"
-version = "1.10.18"
+version = "1.10.19"
description = "Data validation and settings management using python type hints"
optional = false
python-versions = ">=3.7"
files = [
- {file = "pydantic-1.10.18-cp310-cp310-macosx_10_9_x86_64.whl", hash =
"sha256:e405ffcc1254d76bb0e760db101ee8916b620893e6edfbfee563b3c6f7a67c02"},
- {file = "pydantic-1.10.18-cp310-cp310-macosx_11_0_arm64.whl", hash =
"sha256:e306e280ebebc65040034bff1a0a81fd86b2f4f05daac0131f29541cafd80b80"},
- {file =
"pydantic-1.10.18-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:11d9d9b87b50338b1b7de4ebf34fd29fdb0d219dc07ade29effc74d3d2609c62"},
- {file =
"pydantic-1.10.18-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:b661ce52c7b5e5f600c0c3c5839e71918346af2ef20062705ae76b5c16914cab"},
- {file = "pydantic-1.10.18-cp310-cp310-musllinux_1_1_i686.whl", hash =
"sha256:c20f682defc9ef81cd7eaa485879ab29a86a0ba58acf669a78ed868e72bb89e0"},
- {file = "pydantic-1.10.18-cp310-cp310-musllinux_1_1_x86_64.whl", hash =
"sha256:c5ae6b7c8483b1e0bf59e5f1843e4fd8fd405e11df7de217ee65b98eb5462861"},
- {file = "pydantic-1.10.18-cp310-cp310-win_amd64.whl", hash =
"sha256:74fe19dda960b193b0eb82c1f4d2c8e5e26918d9cda858cbf3f41dd28549cb70"},
- {file = "pydantic-1.10.18-cp311-cp311-macosx_10_9_x86_64.whl", hash =
"sha256:72fa46abace0a7743cc697dbb830a41ee84c9db8456e8d77a46d79b537efd7ec"},
- {file = "pydantic-1.10.18-cp311-cp311-macosx_11_0_arm64.whl", hash =
"sha256:ef0fe7ad7cbdb5f372463d42e6ed4ca9c443a52ce544472d8842a0576d830da5"},
- {file =
"pydantic-1.10.18-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:a00e63104346145389b8e8f500bc6a241e729feaf0559b88b8aa513dd2065481"},
- {file =
"pydantic-1.10.18-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:ae6fa2008e1443c46b7b3a5eb03800121868d5ab6bc7cda20b5df3e133cde8b3"},
- {file = "pydantic-1.10.18-cp311-cp311-musllinux_1_1_i686.whl", hash =
"sha256:9f463abafdc92635da4b38807f5b9972276be7c8c5121989768549fceb8d2588"},
- {file = "pydantic-1.10.18-cp311-cp311-musllinux_1_1_x86_64.whl", hash =
"sha256:3445426da503c7e40baccefb2b2989a0c5ce6b163679dd75f55493b460f05a8f"},
- {file = "pydantic-1.10.18-cp311-cp311-win_amd64.whl", hash =
"sha256:467a14ee2183bc9c902579bb2f04c3d3dac00eff52e252850509a562255b2a33"},
- {file = "pydantic-1.10.18-cp312-cp312-macosx_10_9_x86_64.whl", hash =
"sha256:efbc8a7f9cb5fe26122acba1852d8dcd1e125e723727c59dcd244da7bdaa54f2"},
- {file = "pydantic-1.10.18-cp312-cp312-macosx_11_0_arm64.whl", hash =
"sha256:24a4a159d0f7a8e26bf6463b0d3d60871d6a52eac5bb6a07a7df85c806f4c048"},
- {file =
"pydantic-1.10.18-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:b74be007703547dc52e3c37344d130a7bfacca7df112a9e5ceeb840a9ce195c7"},
- {file =
"pydantic-1.10.18-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:fcb20d4cb355195c75000a49bb4a31d75e4295200df620f454bbc6bdf60ca890"},
- {file = "pydantic-1.10.18-cp312-cp312-musllinux_1_1_i686.whl", hash =
"sha256:46f379b8cb8a3585e3f61bf9ae7d606c70d133943f339d38b76e041ec234953f"},
- {file = "pydantic-1.10.18-cp312-cp312-musllinux_1_1_x86_64.whl", hash =
"sha256:cbfbca662ed3729204090c4d09ee4beeecc1a7ecba5a159a94b5a4eb24e3759a"},
- {file = "pydantic-1.10.18-cp312-cp312-win_amd64.whl", hash =
"sha256:c6d0a9f9eccaf7f438671a64acf654ef0d045466e63f9f68a579e2383b63f357"},
- {file = "pydantic-1.10.18-cp37-cp37m-macosx_10_9_x86_64.whl", hash =
"sha256:3d5492dbf953d7d849751917e3b2433fb26010d977aa7a0765c37425a4026ff1"},
- {file =
"pydantic-1.10.18-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:fe734914977eed33033b70bfc097e1baaffb589517863955430bf2e0846ac30f"},
- {file =
"pydantic-1.10.18-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:15fdbe568beaca9aacfccd5ceadfb5f1a235087a127e8af5e48df9d8a45ae85c"},
- {file = "pydantic-1.10.18-cp37-cp37m-musllinux_1_1_i686.whl", hash =
"sha256:c3e742f62198c9eb9201781fbebe64533a3bbf6a76a91b8d438d62b813079dbc"},
- {file = "pydantic-1.10.18-cp37-cp37m-musllinux_1_1_x86_64.whl", hash =
"sha256:19a3bd00b9dafc2cd7250d94d5b578edf7a0bd7daf102617153ff9a8fa37871c"},
- {file = "pydantic-1.10.18-cp37-cp37m-win_amd64.whl", hash =
"sha256:2ce3fcf75b2bae99aa31bd4968de0474ebe8c8258a0110903478bd83dfee4e3b"},
- {file = "pydantic-1.10.18-cp38-cp38-macosx_10_9_x86_64.whl", hash =
"sha256:335a32d72c51a313b33fa3a9b0fe283503272ef6467910338e123f90925f0f03"},
- {file = "pydantic-1.10.18-cp38-cp38-macosx_11_0_arm64.whl", hash =
"sha256:34a3613c7edb8c6fa578e58e9abe3c0f5e7430e0fc34a65a415a1683b9c32d9a"},
- {file =
"pydantic-1.10.18-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:e9ee4e6ca1d9616797fa2e9c0bfb8815912c7d67aca96f77428e316741082a1b"},
- {file =
"pydantic-1.10.18-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:23e8ec1ce4e57b4f441fc91e3c12adba023fedd06868445a5b5f1d48f0ab3682"},
- {file = "pydantic-1.10.18-cp38-cp38-musllinux_1_1_i686.whl", hash =
"sha256:44ae8a3e35a54d2e8fa88ed65e1b08967a9ef8c320819a969bfa09ce5528fafe"},
- {file = "pydantic-1.10.18-cp38-cp38-musllinux_1_1_x86_64.whl", hash =
"sha256:d5389eb3b48a72da28c6e061a247ab224381435256eb541e175798483368fdd3"},
- {file = "pydantic-1.10.18-cp38-cp38-win_amd64.whl", hash =
"sha256:069b9c9fc645474d5ea3653788b544a9e0ccd3dca3ad8c900c4c6eac844b4620"},
- {file = "pydantic-1.10.18-cp39-cp39-macosx_10_9_x86_64.whl", hash =
"sha256:80b982d42515632eb51f60fa1d217dfe0729f008e81a82d1544cc392e0a50ddf"},
- {file = "pydantic-1.10.18-cp39-cp39-macosx_11_0_arm64.whl", hash =
"sha256:aad8771ec8dbf9139b01b56f66386537c6fe4e76c8f7a47c10261b69ad25c2c9"},
- {file =
"pydantic-1.10.18-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:941a2eb0a1509bd7f31e355912eb33b698eb0051730b2eaf9e70e2e1589cae1d"},
- {file =
"pydantic-1.10.18-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:65f7361a09b07915a98efd17fdec23103307a54db2000bb92095457ca758d485"},
- {file = "pydantic-1.10.18-cp39-cp39-musllinux_1_1_i686.whl", hash =
"sha256:6951f3f47cb5ca4da536ab161ac0163cab31417d20c54c6de5ddcab8bc813c3f"},
- {file = "pydantic-1.10.18-cp39-cp39-musllinux_1_1_x86_64.whl", hash =
"sha256:7a4c5eec138a9b52c67f664c7d51d4c7234c5ad65dd8aacd919fb47445a62c86"},
- {file = "pydantic-1.10.18-cp39-cp39-win_amd64.whl", hash =
"sha256:49e26c51ca854286bffc22b69787a8d4063a62bf7d83dc21d44d2ff426108518"},
- {file = "pydantic-1.10.18-py3-none-any.whl", hash =
"sha256:06a189b81ffc52746ec9c8c007f16e5167c8b0a696e1a726369327e3db7b2a82"},
- {file = "pydantic-1.10.18.tar.gz", hash =
"sha256:baebdff1907d1d96a139c25136a9bb7d17e118f133a76a2ef3b845e831e3403a"},
+ {file = "pydantic-1.10.19-cp310-cp310-macosx_10_9_x86_64.whl", hash =
"sha256:a415b9e95fa602b10808113967f72b2da8722061265d6af69268c111c254832d"},
+ {file = "pydantic-1.10.19-cp310-cp310-macosx_11_0_arm64.whl", hash =
"sha256:11965f421f7eb026439d4eb7464e9182fe6d69c3d4d416e464a4485d1ba61ab6"},
+ {file =
"pydantic-1.10.19-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:f5bb81fcfc6d5bff62cd786cbd87480a11d23f16d5376ad2e057c02b3b44df96"},
+ {file =
"pydantic-1.10.19-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:83ee8c9916689f8e6e7d90161e6663ac876be2efd32f61fdcfa3a15e87d4e413"},
+ {file = "pydantic-1.10.19-cp310-cp310-musllinux_1_1_i686.whl", hash =
"sha256:0399094464ae7f28482de22383e667625e38e1516d6b213176df1acdd0c477ea"},
+ {file = "pydantic-1.10.19-cp310-cp310-musllinux_1_1_x86_64.whl", hash =
"sha256:8b2cf5e26da84f2d2dee3f60a3f1782adedcee785567a19b68d0af7e1534bd1f"},
+ {file = "pydantic-1.10.19-cp310-cp310-win_amd64.whl", hash =
"sha256:1fc8cc264afaf47ae6a9bcbd36c018d0c6b89293835d7fb0e5e1a95898062d59"},
+ {file = "pydantic-1.10.19-cp311-cp311-macosx_10_9_x86_64.whl", hash =
"sha256:d7a8a1dd68bac29f08f0a3147de1885f4dccec35d4ea926e6e637fac03cdb4b3"},
+ {file = "pydantic-1.10.19-cp311-cp311-macosx_11_0_arm64.whl", hash =
"sha256:07d00ca5ef0de65dd274005433ce2bb623730271d495a7d190a91c19c5679d34"},
+ {file =
"pydantic-1.10.19-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:ad57004e5d73aee36f1e25e4e73a4bc853b473a1c30f652dc8d86b0a987ffce3"},
+ {file =
"pydantic-1.10.19-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:dce355fe7ae53e3090f7f5fa242423c3a7b53260747aa398b4b3aaf8b25f41c3"},
+ {file = "pydantic-1.10.19-cp311-cp311-musllinux_1_1_i686.whl", hash =
"sha256:0d32227ea9a3bf537a2273fd2fdb6d64ab4d9b83acd9e4e09310a777baaabb98"},
+ {file = "pydantic-1.10.19-cp311-cp311-musllinux_1_1_x86_64.whl", hash =
"sha256:e351df83d1c9cffa53d4e779009a093be70f1d5c6bb7068584086f6a19042526"},
+ {file = "pydantic-1.10.19-cp311-cp311-win_amd64.whl", hash =
"sha256:d8d72553d2f3f57ce547de4fa7dc8e3859927784ab2c88343f1fc1360ff17a08"},
+ {file = "pydantic-1.10.19-cp312-cp312-macosx_10_9_x86_64.whl", hash =
"sha256:d5b5b7c6bafaef90cbb7dafcb225b763edd71d9e22489647ee7df49d6d341890"},
+ {file = "pydantic-1.10.19-cp312-cp312-macosx_11_0_arm64.whl", hash =
"sha256:570ad0aeaf98b5e33ff41af75aba2ef6604ee25ce0431ecd734a28e74a208555"},
+ {file =
"pydantic-1.10.19-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:0890fbd7fec9e151c7512941243d830b2d6076d5df159a2030952d480ab80a4e"},
+ {file =
"pydantic-1.10.19-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:ec5c44e6e9eac5128a9bfd21610df3b8c6b17343285cc185105686888dc81206"},
+ {file = "pydantic-1.10.19-cp312-cp312-musllinux_1_1_i686.whl", hash =
"sha256:6eb56074b11a696e0b66c7181da682e88c00e5cebe6570af8013fcae5e63e186"},
+ {file = "pydantic-1.10.19-cp312-cp312-musllinux_1_1_x86_64.whl", hash =
"sha256:9d7d48fbc5289efd23982a0d68e973a1f37d49064ccd36d86de4543aff21e086"},
+ {file = "pydantic-1.10.19-cp312-cp312-win_amd64.whl", hash =
"sha256:fd34012691fbd4e67bdf4accb1f0682342101015b78327eaae3543583fcd451e"},
+ {file = "pydantic-1.10.19-cp37-cp37m-macosx_10_9_x86_64.whl", hash =
"sha256:4a5d5b877c7d3d9e17399571a8ab042081d22fe6904416a8b20f8af5909e6c8f"},
+ {file =
"pydantic-1.10.19-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:9c46f58ef2df958ed2ea7437a8be0897d5efe9ee480818405338c7da88186fb3"},
+ {file =
"pydantic-1.10.19-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:6d8a38a44bb6a15810084316ed69c854a7c06e0c99c5429f1d664ad52cec353c"},
+ {file = "pydantic-1.10.19-cp37-cp37m-musllinux_1_1_i686.whl", hash =
"sha256:a82746c6d6e91ca17e75f7f333ed41d70fce93af520a8437821dec3ee52dfb10"},
+ {file = "pydantic-1.10.19-cp37-cp37m-musllinux_1_1_x86_64.whl", hash =
"sha256:566bebdbe6bc0ac593fa0f67d62febbad9f8be5433f686dc56401ba4aab034e3"},
+ {file = "pydantic-1.10.19-cp37-cp37m-win_amd64.whl", hash =
"sha256:22a1794e01591884741be56c6fba157c4e99dcc9244beb5a87bd4aa54b84ea8b"},
+ {file = "pydantic-1.10.19-cp38-cp38-macosx_10_9_x86_64.whl", hash =
"sha256:076c49e24b73d346c45f9282d00dbfc16eef7ae27c970583d499f11110d9e5b0"},
+ {file = "pydantic-1.10.19-cp38-cp38-macosx_11_0_arm64.whl", hash =
"sha256:5d4320510682d5a6c88766b2a286d03b87bd3562bf8d78c73d63bab04b21e7b4"},
+ {file =
"pydantic-1.10.19-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:7e66aa0fa7f8aa9d0a620361834f6eb60d01d3e9cea23ca1a92cda99e6f61dac"},
+ {file =
"pydantic-1.10.19-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:d216f8d0484d88ab72ab45d699ac669fe031275e3fa6553e3804e69485449fa0"},
+ {file = "pydantic-1.10.19-cp38-cp38-musllinux_1_1_i686.whl", hash =
"sha256:9f28a81978e936136c44e6a70c65bde7548d87f3807260f73aeffbf76fb94c2f"},
+ {file = "pydantic-1.10.19-cp38-cp38-musllinux_1_1_x86_64.whl", hash =
"sha256:d3449633c207ec3d2d672eedb3edbe753e29bd4e22d2e42a37a2c1406564c20f"},
+ {file = "pydantic-1.10.19-cp38-cp38-win_amd64.whl", hash =
"sha256:7ea24e8614f541d69ea72759ff635df0e612b7dc9d264d43f51364df310081a3"},
+ {file = "pydantic-1.10.19-cp39-cp39-macosx_10_9_x86_64.whl", hash =
"sha256:573254d844f3e64093f72fcd922561d9c5696821ff0900a0db989d8c06ab0c25"},
+ {file = "pydantic-1.10.19-cp39-cp39-macosx_11_0_arm64.whl", hash =
"sha256:ff09600cebe957ecbb4a27496fe34c1d449e7957ed20a202d5029a71a8af2e35"},
+ {file =
"pydantic-1.10.19-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
hash =
"sha256:4739c206bfb6bb2bdc78dcd40bfcebb2361add4ceac6d170e741bb914e9eff0f"},
+ {file =
"pydantic-1.10.19-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",
hash =
"sha256:0bfb5b378b78229119d66ced6adac2e933c67a0aa1d0a7adffbe432f3ec14ce4"},
+ {file = "pydantic-1.10.19-cp39-cp39-musllinux_1_1_i686.whl", hash =
"sha256:7f31742c95e3f9443b8c6fa07c119623e61d76603be9c0d390bcf7e888acabcb"},
+ {file = "pydantic-1.10.19-cp39-cp39-musllinux_1_1_x86_64.whl", hash =
"sha256:c6444368b651a14c2ce2fb22145e1496f7ab23cbdb978590d47c8d34a7bc0289"},
+ {file = "pydantic-1.10.19-cp39-cp39-win_amd64.whl", hash =
"sha256:945407f4d08cd12485757a281fca0e5b41408606228612f421aa4ea1b63a095d"},
+ {file = "pydantic-1.10.19-py3-none-any.whl", hash =
"sha256:2206a1752d9fac011e95ca83926a269fb0ef5536f7e053966d058316e24d929f"},
+ {file = "pydantic-1.10.19.tar.gz", hash =
"sha256:fea36c2065b7a1d28c6819cc2e93387b43dd5d3cf5a1e82d8132ee23f36d1f10"},
]
[package.dependencies]
@@ -3137,13 +3137,13 @@ files = [
[[package]]
name = "sqlparse"
-version = "0.5.1"
+version = "0.5.2"
description = "A non-validating SQL parser."
optional = false
python-versions = ">=3.8"
files = [
- {file = "sqlparse-0.5.1-py3-none-any.whl", hash =
"sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4"},
- {file = "sqlparse-0.5.1.tar.gz", hash =
"sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e"},
+ {file = "sqlparse-0.5.2-py3-none-any.whl", hash =
"sha256:e99bc85c78160918c3e1d9230834ab8d80fc06c59d03f8db2618f65f65dda55e"},
+ {file = "sqlparse-0.5.2.tar.gz", hash =
"sha256:9e37b35e16d1cc652a2545f0997c1deb23ea28fa1f3eefe609eee3063c3b105f"},
]
[package.extras]
@@ -3223,13 +3223,13 @@ tornado = ["tornado (>=4.0,<6.0)", "tornado
(>=4.0,<7.0)"]
[[package]]
name = "tomli"
-version = "2.0.2"
+version = "2.1.0"
description = "A lil' TOML parser"
optional = false
python-versions = ">=3.8"
files = [
- {file = "tomli-2.0.2-py3-none-any.whl", hash =
"sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"},
- {file = "tomli-2.0.2.tar.gz", hash =
"sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"},
+ {file = "tomli-2.1.0-py3-none-any.whl", hash =
"sha256:a5c57c3d1c56f5ccdf89f6523458f60ef716e210fc47c4cfb188c5ba473e0391"},
+ {file = "tomli-2.1.0.tar.gz", hash =
"sha256:3f646cae2aec94e17d04973e4249548320197cfabdf130015d023de4b74d8ab8"},
]
[[package]]
@@ -3968,4 +3968,4 @@ sync = ["kafka-python", "requests"]
[metadata]
lock-version = "2.0"
python-versions = ">=3.8, <3.12"
-content-hash =
"957ba196be529a7924617a968a810a5934461cb43936ed738779123e963fcb63"
+content-hash =
"81b915ab08654027b32031f29cc7d558df4e19e32468f0463b85f6fa53122701"
diff --git a/pyproject.toml b/pyproject.toml
index dab159f..db34eef 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -137,6 +137,7 @@ httpx = "^0.23.3"
confluent-kafka = "^2.0.2"
neo4j = "^5.9.0"
pulsar-client = "3.3.0"
+grpcio = "^1.49.1"
[tool.poetry.group.lint.dependencies]
pylint = '2.13.9'
diff --git a/skywalking/__init__.py b/skywalking/__init__.py
index ec1dc09..b8005a5 100644
--- a/skywalking/__init__.py
+++ b/skywalking/__init__.py
@@ -55,6 +55,7 @@ class Component(Enum):
AIORedis = 7017
Websockets = 7018
HTTPX = 7019
+ Grpc = 23
class Layer(Enum):
@@ -89,6 +90,6 @@ LogItem = namedtuple('LogItem', 'key val')
class Log(object):
- def __init__(self, timestamp: time = time.time(), items: List[LogItem] =
None): # noqa
+ def __init__(self, timestamp: time = time.time(), items: List[LogItem] =
None): # noqa
self.timestamp = timestamp
self.items = items or []
diff --git a/skywalking/config.py b/skywalking/config.py
index 62c8956..5a2b1ca 100644
--- a/skywalking/config.py
+++ b/skywalking/config.py
@@ -37,6 +37,7 @@ from typing import List, Pattern
RE_IGNORE_PATH: Pattern = re.compile('^$')
RE_HTTP_IGNORE_METHOD: Pattern = RE_IGNORE_PATH
+RE_GRPC_IGNORED_METHODS: Pattern = RE_IGNORE_PATH
options = None # here to include 'options' in globals
options = globals().copy()
@@ -212,6 +213,8 @@ plugin_fastapi_collect_http_params: bool =
os.getenv('SW_PLUGIN_FASTAPI_COLLECT_
plugin_bottle_collect_http_params: bool =
os.getenv('SW_PLUGIN_BOTTLE_COLLECT_HTTP_PARAMS', '').lower() == 'true'
# The maximum length of `celery` functions parameters, longer than this will
be truncated, 0 turns off
plugin_celery_parameters_length: int =
int(os.getenv('SW_PLUGIN_CELERY_PARAMETERS_LENGTH', '512'))
+# Comma-delimited list of user-defined grpc methods to ignore, like
/package.Service/Method1,/package.Service/Method2
+plugin_grpc_ignored_methods: str = os.getenv('SW_PLUGIN_GRPC_IGNORED_METHODS',
'').upper()
# BEGIN: Sampling Configurations
# The number of samples to take in every 3 seconds, 0 turns off
@@ -284,6 +287,7 @@ def finalize_regex() -> None:
reesc = re.compile(r'([.*+?^=!:${}()|\[\]\\])')
suffix = r'^.+(?:' + '|'.join(reesc.sub(r'\\\1', s.strip()) for s in
agent_ignore_suffix.split(',')) + ')$'
method = r'^' + '|'.join(s.strip() for s in
plugin_http_ignore_method.split(',')) + '$'
+ grpc_method = r'^' + '|'.join(s.strip() for s in
plugin_grpc_ignored_methods.split(',')) + '$'
path = '^(?:' + \
'|'.join( # replaces ","
'/(?:[^/]*/)*'.join( # replaces "/**/"
@@ -297,15 +301,20 @@ def finalize_regex() -> None:
) for p0 in agent_trace_ignore_path.split(',')
) + ')$'
- global RE_IGNORE_PATH, RE_HTTP_IGNORE_METHOD
+ global RE_IGNORE_PATH, RE_HTTP_IGNORE_METHOD, RE_GRPC_IGNORED_METHODS
RE_IGNORE_PATH = re.compile(f'{suffix}|{path}')
RE_HTTP_IGNORE_METHOD = re.compile(method, re.IGNORECASE)
+ RE_GRPC_IGNORED_METHODS = re.compile(grpc_method, re.IGNORECASE)
def ignore_http_method_check(method: str):
return RE_HTTP_IGNORE_METHOD.match(method)
+def ignore_grpc_method_check(method: str):
+ return RE_GRPC_IGNORED_METHODS.match(method)
+
+
def finalize() -> None:
"""
invokes finalizers
diff --git a/skywalking/meter/pvm/data_source.py
b/skywalking/meter/pvm/data_source.py
index 3f97c78..4a54122 100644
--- a/skywalking/meter/pvm/data_source.py
+++ b/skywalking/meter/pvm/data_source.py
@@ -23,4 +23,4 @@ class DataSource:
for name in dir(self):
if name.endswith('generator'):
generator = getattr(self, name)()
- Gauge.Builder('instance_pvm_' + name[:-10], generator).build()
+ Gauge.Builder(f'instance_pvm_{name[:-10]}', generator).build()
diff --git a/skywalking/plugins/sw_grpc.py b/skywalking/plugins/sw_grpc.py
new file mode 100644
index 0000000..12b03cb
--- /dev/null
+++ b/skywalking/plugins/sw_grpc.py
@@ -0,0 +1,477 @@
+#
+# 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 asyncio import iscoroutine
+from concurrent.futures import Executor
+from typing import Any, Awaitable, Callable, List, NamedTuple, Optional,
Sequence, Tuple, Union
+
+from skywalking import Component, Layer, config
+from skywalking.trace.carrier import Carrier
+from skywalking.trace.context import NoopContext, get_context
+from skywalking.trace.span import NoopSpan
+from skywalking.trace.tags import TagGrpcMethod, TagGrpcStatusCode, TagGrpcUrl
+
+link_vector = ['https://grpc.io/docs/languages/python']
+support_matrix = {'grpcio': {'>=3.8': ['1.*']}}
+note = """"""
+
+
+def _get_factory_and_method(rpc_handler: Any) -> Tuple[Callable[..., Any],
Callable[..., Any]]:
+ import grpc
+
+ if rpc_handler.unary_unary:
+ return grpc.unary_unary_rpc_method_handler, rpc_handler.unary_unary
+ elif rpc_handler.unary_stream:
+ return grpc.unary_stream_rpc_method_handler, rpc_handler.unary_stream
+ elif rpc_handler.stream_unary:
+ return grpc.stream_unary_rpc_method_handler, rpc_handler.stream_unary
+ elif rpc_handler.stream_stream:
+ return grpc.stream_stream_rpc_method_handler, rpc_handler.stream_stream
+ else:
+ raise RuntimeError('RPC handler implementation does not exist')
+
+
+def _restore_carrier(handler_call_details: Any) -> Carrier:
+ metadata_map = dict(handler_call_details.invocation_metadata or ())
+
+ carrier = Carrier()
+ for item in carrier:
+ val = metadata_map.get(item.key)
+ if val is not None:
+ item.val = val
+ return carrier
+
+
+def get_method_name(details: Any) -> str:
+ method_name = details.method
+ if type(method_name) is bytes:
+ return method_name.decode()
+ if type(method_name) is str:
+ return method_name
+ return str(method_name)
+
+
+def install_sync() -> None:
+ import grpc
+ from grpc import _channel
+
+ def install_server() -> None:
+ _grpc_server = grpc.server
+
+ def _make_invoke_intercept_method(
+ is_response_streaming: bool,
+ next_handler_method: Callable[..., Any],
+ handler_call_details: grpc.HandlerCallDetails,
+ ) -> Callable[[Any, grpc.ServicerContext], Any]:
+
+ def invoke_intercept_method(request_or_iterator: Any, context:
grpc.ServicerContext) -> Any:
+
+ carrier = _restore_carrier(handler_call_details)
+ method_name = get_method_name(handler_call_details)
+ with (
+ NoopSpan(NoopContext())
+ if config.ignore_grpc_method_check(method_name)
+ else get_context().new_entry_span(op=method_name,
carrier=carrier)
+ ) as span:
+ span.layer = Layer.RPCFramework
+ span.tag(TagGrpcMethod(method_name))
+ span.component = Component.Grpc
+ span.peer = context.peer()
+ try:
+ return next_handler_method(request_or_iterator,
context)
+ except grpc.RpcError as e:
+ if hasattr(e, 'code'):
+ span.tag(TagGrpcStatusCode(e.code()))
+ else:
+
span.tag(TagGrpcStatusCode(grpc.StatusCode.UNKNOWN))
+ span.raised()
+ raise e
+
+ def invoke_intercept_method_response_streaming(
+ request_or_iterator: Any, context: grpc.ServicerContext
+ ) -> Any:
+ carrier = _restore_carrier(handler_call_details)
+ method_name = get_method_name(handler_call_details)
+ with (
+ NoopSpan(NoopContext())
+ if config.ignore_grpc_method_check(method_name)
+ else get_context().new_entry_span(op=method_name,
carrier=carrier)
+ ) as span:
+ span.layer = Layer.RPCFramework
+ span.tag(TagGrpcMethod(method_name))
+ span.component = Component.Grpc
+ span.peer = context.peer()
+ try:
+ yield from next_handler_method(request_or_iterator,
context)
+ except grpc.RpcError as e:
+ if hasattr(e, 'code'):
+ span.tag(TagGrpcStatusCode(e.code()))
+ else:
+
span.tag(TagGrpcStatusCode(grpc.StatusCode.UNKNOWN))
+ span.raised()
+ raise e
+
+ return invoke_intercept_method_response_streaming if
is_response_streaming else invoke_intercept_method
+
+ class ServerInterceptor(grpc.ServerInterceptor):
+
+ def intercept_service(
+ self,
+ continuation: Callable[[grpc.HandlerCallDetails],
grpc.RpcMethodHandler],
+ handler_call_details: grpc.HandlerCallDetails,
+ ) -> grpc.RpcMethodHandler:
+ next_handler = continuation(handler_call_details)
+
+ handler_factory, next_handler_method =
_get_factory_and_method(next_handler)
+
+ return handler_factory(
+ _make_invoke_intercept_method(
+ bool(next_handler.response_streaming),
next_handler_method, handler_call_details
+ ),
+ request_deserializer=next_handler.request_deserializer,
+ response_serializer=next_handler.response_serializer,
+ )
+
+ def _sw_grpc_server(
+ thread_pool: Optional[Executor] = None,
+ handlers: Optional[Sequence[grpc.GenericRpcHandler]] = None,
+ interceptors: Optional[Sequence[Any]] = None,
+ options: Optional[Any] = None,
+ maximum_concurrent_rpcs: Optional[int] = None,
+ compression: Optional[grpc.Compression] = None,
+ xds: bool = False,
+ ):
+ _sw_interceptors = [ServerInterceptor()]
+ if interceptors is not None:
+ _sw_interceptors.extend(interceptors)
+ return _grpc_server(
+ thread_pool,
+ handlers,
+ _sw_interceptors,
+ options,
+ maximum_concurrent_rpcs,
+ compression,
+ xds,
+ )
+
+ grpc.server = _sw_grpc_server
+
+ def install_client() -> None:
+ _grpc_channel = _channel.Channel
+
+ class _ClientCallDetails(NamedTuple):
+ method: str
+ timeout: Optional[float]
+ metadata: Optional[Sequence[Tuple[str, Union[str, bytes]]]]
+ credentials: Optional[grpc.CallCredentials]
+ wait_for_ready: Optional[bool]
+ compression: Any
+
+ class _SWClientCallDetails(_ClientCallDetails, grpc.ClientCallDetails):
+ pass
+
+ class _ClientInterceptor(
+ grpc.UnaryUnaryClientInterceptor,
+ grpc.UnaryStreamClientInterceptor,
+ grpc.StreamUnaryClientInterceptor,
+ grpc.StreamStreamClientInterceptor,
+ ):
+ def __init__(self, target: str):
+ self.target = target
+
+ def _intercept(
+ self,
+ continuation: Callable[..., Any],
+ client_call_details: grpc.ClientCallDetails,
+ request: Any,
+ ):
+ method_name = get_method_name(client_call_details)
+ with (
+ NoopSpan(NoopContext())
+ if config.ignore_grpc_method_check(method_name)
+ else get_context().new_exit_span(op=method_name,
peer=self.target, component=Component.Grpc)
+ ) as span:
+ span.layer = Layer.RPCFramework
+ span.tag(TagGrpcMethod(method_name))
+ span.tag(TagGrpcUrl(self.target))
+ carrier = span.inject()
+ metadata = list(client_call_details.metadata or [])
+ for item in carrier:
+ metadata.append((item.key, item.val))
+ new_client_call_details = _SWClientCallDetails(
+ client_call_details.method,
+ client_call_details.timeout,
+ metadata,
+ client_call_details.credentials,
+ client_call_details.wait_for_ready,
+ client_call_details.compression,
+ )
+ return continuation(new_client_call_details, request)
+
+ def intercept_unary_unary(self, continuation, client_call_details,
request):
+ return self._intercept(continuation, client_call_details,
request)
+
+ def intercept_unary_stream(self, continuation,
client_call_details, request):
+ return self._intercept(continuation, client_call_details,
request)
+
+ def intercept_stream_unary(self, continuation,
client_call_details, request_iterator):
+ return self._intercept(continuation, client_call_details,
request_iterator)
+
+ def intercept_stream_stream(self, continuation,
client_call_details, request_iterator):
+ return self._intercept(continuation, client_call_details,
request_iterator)
+
+ def _sw_grpc_channel_factory(target: str, *args: Any, **kwargs: Any):
+ c = _grpc_channel(target, *args, **kwargs)
+ if target == config.agent_collector_backend_services:
+ return c
+ return grpc.intercept_channel(c, _ClientInterceptor(target))
+
+ _channel.Channel = _sw_grpc_channel_factory
+
+ install_client()
+ install_server()
+
+
+def install_async() -> None:
+ import grpc
+ from grpc.aio import _channel as _aio_channel
+
+ def install_async_server() -> None:
+ _grpc_aio_server = grpc.aio.server
+
+ def _make_invoke_intercept_method(
+ is_response_streaming: bool,
+ next_handler_method: Callable[..., Any],
+ handler_call_details: grpc.HandlerCallDetails,
+ ) -> Callable[[Any, grpc.aio.ServicerContext[Any, Any]],
Awaitable[Any]]:
+
+ async def invoke_intercept_method(
+ request_or_iterator: Any, context:
grpc.aio.ServicerContext[Any, Any]
+ ) -> Any:
+
+ carrier = _restore_carrier(handler_call_details)
+ method_name = get_method_name(handler_call_details)
+ with (
+ NoopSpan(NoopContext())
+ if config.ignore_grpc_method_check(method_name)
+ else get_context().new_entry_span(op=method_name,
carrier=carrier)
+ ) as span:
+ span.layer = Layer.RPCFramework
+ span.tag(TagGrpcMethod(method_name))
+ span.component = Component.Grpc
+ span.peer = context.peer()
+ try:
+ return await next_handler_method(request_or_iterator,
context)
+ except grpc.RpcError as e:
+ if hasattr(e, 'code'):
+ span.tag(TagGrpcStatusCode(e.code()))
+ else:
+
span.tag(TagGrpcStatusCode(grpc.StatusCode.UNKNOWN))
+ span.raised()
+ raise e
+
+ async def invoke_intercept_method_response_streaming(
+ request_or_iterator: Any, context:
grpc.aio.ServicerContext[Any, Any]
+ ) -> Any:
+ carrier = _restore_carrier(handler_call_details)
+ method_name = get_method_name(handler_call_details)
+ with (
+ NoopSpan(NoopContext())
+ if config.ignore_grpc_method_check(method_name)
+ else get_context().new_entry_span(op=method_name,
carrier=carrier)
+ ) as span:
+ span.layer = Layer.RPCFramework
+ span.tag(TagGrpcMethod(method_name))
+ span.component = Component.Grpc
+ span.peer = context.peer()
+ try:
+ coroutine_or_asyncgen =
next_handler_method(request_or_iterator, context)
+ async for r in (
+ await coroutine_or_asyncgen if
iscoroutine(coroutine_or_asyncgen) else coroutine_or_asyncgen
+ ):
+ yield r
+ except grpc.RpcError as e:
+ if hasattr(e, 'code'):
+ span.tag(TagGrpcStatusCode(e.code()))
+ else:
+
span.tag(TagGrpcStatusCode(grpc.StatusCode.UNKNOWN))
+ span.raised()
+ raise e
+
+ return invoke_intercept_method_response_streaming if
is_response_streaming else invoke_intercept_method
+
+ class ServerInterceptor(grpc.aio.ServerInterceptor):
+
+ async def intercept_service(
+ self,
+ continuation: Callable[[grpc.HandlerCallDetails],
Awaitable[grpc.RpcMethodHandler]],
+ handler_call_details: grpc.HandlerCallDetails,
+ ) -> grpc.RpcMethodHandler:
+ next_handler = await continuation(handler_call_details)
+
+ handler_factory, next_handler_method =
_get_factory_and_method(next_handler)
+ return handler_factory(
+ _make_invoke_intercept_method(
+ bool(next_handler.response_streaming),
next_handler_method, handler_call_details
+ ),
+ request_deserializer=next_handler.request_deserializer,
+ response_serializer=next_handler.response_serializer,
+ )
+
+ def _sw_grpc_aio_server(
+ migration_thread_pool: Optional[Executor] = None,
+ handlers: Optional[Sequence[grpc.GenericRpcHandler]] = None,
+ interceptors: Optional[Sequence[Any]] = None,
+ options: Optional[grpc.aio.ChannelArgumentType] = None,
+ maximum_concurrent_rpcs: Optional[int] = None,
+ compression: Optional[grpc.Compression] = None,
+ ):
+ _sw_interceptors = [ServerInterceptor()]
+ if interceptors is not None:
+ _sw_interceptors.extend(interceptors)
+ return _grpc_aio_server(
+ migration_thread_pool,
+ handlers,
+ _sw_interceptors,
+ options,
+ maximum_concurrent_rpcs,
+ compression,
+ )
+
+ grpc.aio.server = _sw_grpc_aio_server
+
+ def install_async_client() -> None:
+ _aio_grpc_channel = _aio_channel.Channel
+
+ class _AioClientCallDetails(NamedTuple):
+ method: str
+ timeout: Optional[float]
+ metadata: Optional[grpc.aio.Metadata]
+ credentials: Optional[grpc.CallCredentials]
+ wait_for_ready: Optional[bool]
+
+ class _SWAioClientCallDetails(_AioClientCallDetails,
grpc.aio.ClientCallDetails):
+ pass
+
+ class _AioClientInterceptor:
+ def __init__(self, target: str):
+ self.target = target
+
+ async def _intercept(
+ self,
+ continuation: Callable[..., Any],
+ client_call_details: grpc.aio.ClientCallDetails,
+ request: Any,
+ ):
+ method_name = get_method_name(client_call_details)
+ span = (
+ NoopSpan(NoopContext())
+ if config.ignore_grpc_method_check(method_name)
+ else get_context().new_exit_span(op=method_name,
peer=self.target, component=Component.Grpc)
+ )
+ with span:
+ span.layer = Layer.RPCFramework
+ span.tag(TagGrpcMethod(method_name))
+ span.tag(TagGrpcUrl(self.target))
+ carrier = span.inject()
+ metadata = client_call_details.metadata or
grpc.aio.Metadata()
+ for item in carrier:
+ metadata.add(item.key, item.val)
+ new_client_call_details = _SWAioClientCallDetails(
+ client_call_details.method,
+ client_call_details.timeout,
+ metadata,
+ client_call_details.credentials,
+ client_call_details.wait_for_ready,
+ )
+ return await continuation(new_client_call_details, request)
+
+ class _AioClientUnaryUnaryInterceptor(_AioClientInterceptor,
grpc.aio.UnaryUnaryClientInterceptor):
+
+ async def intercept_unary_unary(
+ self,
+ continuation: Callable[
+ [grpc.aio.ClientCallDetails,
grpc.aio._typing.RequestType], grpc.aio._call.UnaryUnaryCall
+ ],
+ client_call_details: grpc.aio.ClientCallDetails,
+ request: grpc.aio._typing.RequestType,
+ ) -> grpc.aio._call.UnaryUnaryCall:
+ return await self._intercept(continuation,
client_call_details, request)
+
+ class _AioClientUnaryStreamInterceptor(_AioClientInterceptor,
grpc.aio.UnaryStreamClientInterceptor):
+
+ async def intercept_unary_stream(
+ self,
+ continuation: Callable[
+ [grpc.aio.ClientCallDetails,
grpc.aio._typing.RequestType], grpc.aio._call.UnaryStreamCall
+ ],
+ client_call_details: grpc.aio.ClientCallDetails,
+ request: grpc.aio._typing.RequestType,
+ ) -> grpc.aio._call.UnaryStreamCall:
+ return await self._intercept(continuation,
client_call_details, request)
+
+ class _AioClientStreamUnaryInterceptor(_AioClientInterceptor,
grpc.aio.StreamUnaryClientInterceptor):
+
+ async def intercept_stream_unary(
+ self,
+ continuation: Callable[
+ [grpc.aio.ClientCallDetails,
grpc.aio._typing.RequestType], grpc.aio._call.StreamUnaryCall
+ ],
+ client_call_details: grpc.aio.ClientCallDetails,
+ request_iterator: grpc.aio._typing.RequestIterableType,
+ ) -> grpc.aio._call.StreamUnaryCall:
+ return await self._intercept(continuation,
client_call_details, request_iterator)
+
+ class _AioClientStreamStreamInterceptor(_AioClientInterceptor,
grpc.aio.StreamStreamClientInterceptor):
+
+ async def intercept_stream_stream(
+ self,
+ continuation: Callable[
+ [grpc.aio.ClientCallDetails,
grpc.aio._typing.RequestType], grpc.aio._call.StreamStreamCall
+ ],
+ client_call_details: grpc.aio.ClientCallDetails,
+ request_iterator: grpc.aio._typing.RequestIterableType,
+ ) -> grpc.aio._call.StreamStreamCall:
+ return await self._intercept(continuation,
client_call_details, request_iterator)
+
+ def _sw_grpc_aio_channel_factory(
+ target: str,
+ options: grpc.aio.ChannelArgumentType,
+ credentials: Optional[grpc.ChannelCredentials],
+ compression: Optional[grpc.Compression],
+ interceptors: Optional[Sequence[grpc.aio.ClientInterceptor]],
+ ):
+ if target == config.agent_collector_backend_services:
+ return _aio_grpc_channel(target, options, credentials,
compression, interceptors)
+ _sw_interceptors: List[grpc.aio.ClientInterceptor] = [
+ _AioClientUnaryUnaryInterceptor(target),
+ _AioClientUnaryStreamInterceptor(target),
+ _AioClientStreamUnaryInterceptor(target),
+ _AioClientStreamStreamInterceptor(target),
+ ]
+ _sw_interceptors.extend(interceptors or [])
+ return _aio_grpc_channel(target, options, credentials,
compression, _sw_interceptors)
+
+ _aio_channel.Channel = _sw_grpc_aio_channel_factory
+
+ install_async_client()
+ install_async_server()
+
+
+def install():
+ install_sync()
+ install_async()
diff --git a/skywalking/trace/context.py b/skywalking/trace/context.py
index db52935..11ec3da 100644
--- a/skywalking/trace/context.py
+++ b/skywalking/trace/context.py
@@ -49,7 +49,7 @@ try: # attempt to use async-local instead of thread-local
context and spans
return spans
def _spans_dup():
- spans = __spans.get()[:]
+ spans = __spans.get([])[:]
__spans.set(spans)
return spans
diff --git a/skywalking/trace/tags.py b/skywalking/trace/tags.py
index a1288c4..11b0519 100644
--- a/skywalking/trace/tags.py
+++ b/skywalking/trace/tags.py
@@ -15,6 +15,7 @@
# limitations under the License.
#
+
class Tag:
key: str = ''
overridable: bool = True
@@ -93,3 +94,15 @@ class TagMqQueue(Tag):
class TagCeleryParameters(Tag):
key = 'celery.parameters'
+
+
+class TagGrpcMethod(Tag):
+ key = 'grpc.method'
+
+
+class TagGrpcUrl(Tag):
+ key = 'grpc.url'
+
+
+class TagGrpcStatusCode(Tag):
+ key = 'grpc.status_code'
diff --git a/skywalking/meter/pvm/data_source.py
b/tests/plugin/web/sw_grpc/__init__.py
similarity index 73%
copy from skywalking/meter/pvm/data_source.py
copy to tests/plugin/web/sw_grpc/__init__.py
index 3f97c78..b1312a0 100644
--- a/skywalking/meter/pvm/data_source.py
+++ b/tests/plugin/web/sw_grpc/__init__.py
@@ -14,13 +14,3 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-
-from skywalking.meter.gauge import Gauge
-
-
-class DataSource:
- def register(self):
- for name in dir(self):
- if name.endswith('generator'):
- generator = getattr(self, name)()
- Gauge.Builder('instance_pvm_' + name[:-10], generator).build()
diff --git a/tests/plugin/web/sw_grpc/docker-compose.yml
b/tests/plugin/web/sw_grpc/docker-compose.yml
new file mode 100644
index 0000000..def423b
--- /dev/null
+++ b/tests/plugin/web/sw_grpc/docker-compose.yml
@@ -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.
+#
+
+version: '2.1'
+
+services:
+ collector:
+ extends:
+ service: collector
+ file: ../../docker-compose.base.yml
+
+ provider:
+ extends:
+ service: agent
+ file: ../../docker-compose.base.yml
+ ports:
+ - 50051:50051
+ volumes:
+ - .:/app
+ command: ['bash', '-c', 'pip install -r /app/requirements.txt && python -m
grpc_tools.protoc -I/app --python_out=/tmp --grpc_python_out=/tmp example.proto
&& PYTHONPATH=/tmp sw-python run python3 /app/services/provider.py']
+ depends_on:
+ collector:
+ condition: service_healthy
+ healthcheck:
+ test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/50051"]
+ interval: 5s
+ timeout: 60s
+ retries: 120
+ environment:
+ SW_AGENT_NAME: provider
+ SW_AGENT_LOGGING_LEVEL: DEBUG
+
+ consumer:
+ extends:
+ service: agent
+ file: ../../docker-compose.base.yml
+ ports:
+ - 50052:50052
+ volumes:
+ - .:/app
+ command: ['bash', '-c', 'pip install -r /app/requirements.txt && python -m
grpc_tools.protoc -I/app --python_out=/tmp --grpc_python_out=/tmp example.proto
&& PYTHONPATH=/tmp sw-python run python3 /app/services/consumer.py']
+ depends_on:
+ collector:
+ condition: service_healthy
+ provider:
+ condition: service_healthy
+ healthcheck:
+ test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/50051"]
+ interval: 5s
+ timeout: 60s
+ retries: 120
+ environment:
+ SW_AGENT_NAME: consumer
+ SW_AGENT_LOGGING_LEVEL: DEBUG
+
+ aio_provider:
+ extends:
+ service: agent
+ file: ../../docker-compose.base.yml
+ ports:
+ - 50061:50061
+ volumes:
+ - .:/app
+ command: ['bash', '-c', 'pip install -r /app/requirements.txt && python -m
grpc_tools.protoc -I/app --python_out=/tmp --grpc_python_out=/tmp example.proto
&& PYTHONPATH=/tmp sw-python run python3 /app/services/aio_provider.py']
+ depends_on:
+ collector:
+ condition: service_healthy
+ healthcheck:
+ test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/50061"]
+ interval: 5s
+ timeout: 60s
+ retries: 120
+ environment:
+ SW_AGENT_NAME: aio_provider
+ SW_AGENT_LOGGING_LEVEL: DEBUG
+
+ aio_consumer:
+ extends:
+ service: agent
+ file: ../../docker-compose.base.yml
+ ports:
+ - 50062:50062
+ volumes:
+ - .:/app
+ command: ['bash', '-c', 'pip install -r /app/requirements.txt && python -m
grpc_tools.protoc -I/app --python_out=/tmp --grpc_python_out=/tmp example.proto
&& PYTHONPATH=/tmp sw-python run python3 /app/services/aio_consumer.py']
+ depends_on:
+ collector:
+ condition: service_healthy
+ provider:
+ condition: service_healthy
+ healthcheck:
+ test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/50062"]
+ interval: 5s
+ timeout: 60s
+ retries: 120
+ environment:
+ SW_AGENT_NAME: aio_consumer
+ SW_AGENT_LOGGING_LEVEL: DEBUG
+networks:
+ beyond:
diff --git a/tests/plugin/web/sw_grpc/example.proto
b/tests/plugin/web/sw_grpc/example.proto
new file mode 100644
index 0000000..204235f
--- /dev/null
+++ b/tests/plugin/web/sw_grpc/example.proto
@@ -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.
+//
+//
+
+syntax = "proto3";
+
+package example;
+
+// The greeting service definition.
+service Greeter {
+ // Sends a greeting
+ rpc SayHello (HelloRequest) returns (HelloReply) {}
+ rpc SayHello1 (HelloRequest) returns (HelloReply) {}
+ rpc SayHelloUS (HelloRequest) returns (stream HelloReply) {}
+ rpc SayHelloSU (stream HelloRequest) returns (HelloReply) {}
+ rpc SayHelloSS (stream HelloRequest) returns (stream HelloReply) {}
+}
+
+// The request message containing the user's name.
+message HelloRequest {
+ string name = 1;
+}
+
+// The response message containing the greetings.
+message HelloReply {
+ string message = 1;
+}
diff --git a/tests/plugin/web/sw_grpc/expected.data.yml
b/tests/plugin/web/sw_grpc/expected.data.yml
new file mode 100644
index 0000000..7eae4f8
--- /dev/null
+++ b/tests/plugin/web/sw_grpc/expected.data.yml
@@ -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.
+#
+
+segmentItems:
+ - serviceName: provider
+ segmentSize: 4
+ segments:
+ - segmentId: not null
+ spans:
+ - operationName: /example.Greeter/SayHello
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: RPCFramework
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 23
+ isError: false
+ spanType: Entry
+ peer: not null
+ skipAnalysis: false
+ tags:
+ - { key: grpc.method, value: /example.Greeter/SayHello }
+ refs:
+ - {
+ parentEndpoint: /example.Greeter/SayHello,
+ networkAddress: "provider:50051",
+ refType: CrossProcess,
+ parentSpanId: 1,
+ parentTraceSegmentId: not null,
+ parentServiceInstance: not null,
+ parentService: consumer,
+ traceId: not null,
+ }
+ - segmentId: not null
+ spans:
+ - operationName: /example.Greeter/SayHelloUS
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: RPCFramework
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 23
+ isError: false
+ spanType: Entry
+ peer: not null
+ skipAnalysis: false
+ tags:
+ - { key: grpc.method, value: /example.Greeter/SayHelloUS }
+ refs:
+ - {
+ parentEndpoint: /example.Greeter/SayHelloUS,
+ networkAddress: "provider:50051",
+ refType: CrossProcess,
+ parentSpanId: 2,
+ parentTraceSegmentId: not null,
+ parentServiceInstance: not null,
+ parentService: consumer,
+ traceId: not null,
+ }
+ - segmentId: not null
+ spans:
+ - operationName: /example.Greeter/SayHelloSU
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: RPCFramework
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 23
+ isError: false
+ spanType: Entry
+ peer: not null
+ skipAnalysis: false
+ tags:
+ - { key: grpc.method, value: /example.Greeter/SayHelloSU }
+ refs:
+ - {
+ parentEndpoint: /example.Greeter/SayHelloSU,
+ networkAddress: "provider:50051",
+ refType: CrossProcess,
+ parentSpanId: 3,
+ parentTraceSegmentId: not null,
+ parentServiceInstance: not null,
+ parentService: consumer,
+ traceId: not null,
+ }
+ - segmentId: not null
+ spans:
+ - operationName: /example.Greeter/SayHelloSS
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: RPCFramework
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 23
+ isError: false
+ spanType: Entry
+ peer: not null
+ skipAnalysis: false
+ tags:
+ - { key: grpc.method, value: /example.Greeter/SayHelloSS }
+ refs:
+ - {
+ parentEndpoint: /example.Greeter/SayHelloSS,
+ networkAddress: "provider:50051",
+ refType: CrossProcess,
+ parentSpanId: 4,
+ parentTraceSegmentId: not null,
+ parentServiceInstance: not null,
+ parentService: consumer,
+ traceId: not null,
+ }
+ - serviceName: consumer
+ segmentSize: 1
+ segments:
+ - segmentId: not null
+ spans:
+ - operationName: /example.Greeter/SayHello
+ parentSpanId: 0
+ spanId: 1
+ spanLayer: RPCFramework
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 23
+ isError: false
+ spanType: Exit
+ peer: provider:50051
+ skipAnalysis: false
+ tags:
+ - { key: grpc.method, value: /example.Greeter/SayHello }
+ - { key: grpc.url, value: "provider:50051" }
+ - operationName: /example.Greeter/SayHelloUS
+ parentSpanId: 0
+ spanId: 2
+ spanLayer: RPCFramework
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 23
+ isError: false
+ spanType: Exit
+ peer: provider:50051
+ skipAnalysis: false
+ tags:
+ - { key: grpc.method, value: /example.Greeter/SayHelloUS }
+ - { key: grpc.url, value: "provider:50051" }
+ - operationName: /example.Greeter/SayHelloSU
+ parentSpanId: 0
+ spanId: 3
+ spanLayer: RPCFramework
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 23
+ isError: false
+ spanType: Exit
+ peer: provider:50051
+ skipAnalysis: false
+ tags:
+ - { key: grpc.method, value: /example.Greeter/SayHelloSU }
+ - { key: grpc.url, value: "provider:50051" }
+ - operationName: /example.Greeter/SayHelloSS
+ parentSpanId: 0
+ spanId: 4
+ spanLayer: RPCFramework
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 23
+ isError: false
+ spanType: Exit
+ peer: provider:50051
+ skipAnalysis: false
+ tags:
+ - { key: grpc.method, value: /example.Greeter/SayHelloSS }
+ - { key: grpc.url, value: "provider:50051" }
+ - operationName: /
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Http
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 7000
+ isError: false
+ spanType: Entry
+ peer: not null
+ skipAnalysis: false
+ tags:
+ - { key: http.method, value: GET }
+ - { key: http.url, value: "http://127.0.0.1:50052/" }
+ - { key: http.status_code, value: "200" }
+ - serviceName: aio_provider
+ segmentSize: 4
+ segments:
+ - segmentId: not null
+ spans:
+ - operationName: /example.Greeter/SayHello
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: RPCFramework
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 23
+ isError: false
+ spanType: Entry
+ peer: not null
+ skipAnalysis: false
+ tags:
+ - { key: grpc.method, value: /example.Greeter/SayHello }
+ refs:
+ - {
+ parentEndpoint: /example.Greeter/SayHello,
+ networkAddress: "aio_provider:50061",
+ refType: CrossProcess,
+ parentSpanId: 1,
+ parentTraceSegmentId: not null,
+ parentServiceInstance: not null,
+ parentService: aio_consumer,
+ traceId: not null,
+ }
+ - segmentId: not null
+ spans:
+ - operationName: /example.Greeter/SayHelloUS
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: RPCFramework
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 23
+ isError: false
+ spanType: Entry
+ peer: not null
+ skipAnalysis: false
+ tags:
+ - { key: grpc.method, value: /example.Greeter/SayHelloUS }
+ refs:
+ - {
+ parentEndpoint: /example.Greeter/SayHelloUS,
+ networkAddress: "aio_provider:50061",
+ refType: CrossProcess,
+ parentSpanId: 2,
+ parentTraceSegmentId: not null,
+ parentServiceInstance: not null,
+ parentService: aio_consumer,
+ traceId: not null,
+ }
+ - segmentId: not null
+ spans:
+ - operationName: /example.Greeter/SayHelloSU
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: RPCFramework
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 23
+ isError: false
+ spanType: Entry
+ peer: not null
+ skipAnalysis: false
+ tags:
+ - { key: grpc.method, value: /example.Greeter/SayHelloSU }
+ refs:
+ - {
+ parentEndpoint: /example.Greeter/SayHelloSU,
+ networkAddress: "aio_provider:50061",
+ refType: CrossProcess,
+ parentSpanId: 3,
+ parentTraceSegmentId: not null,
+ parentServiceInstance: not null,
+ parentService: aio_consumer,
+ traceId: not null,
+ }
+ - segmentId: not null
+ spans:
+ - operationName: /example.Greeter/SayHelloSS
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: RPCFramework
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 23
+ isError: false
+ spanType: Entry
+ peer: not null
+ skipAnalysis: false
+ tags:
+ - { key: grpc.method, value: /example.Greeter/SayHelloSS }
+ refs:
+ - {
+ parentEndpoint: /example.Greeter/SayHelloSS,
+ networkAddress: "aio_provider:50061",
+ refType: CrossProcess,
+ parentSpanId: 4,
+ parentTraceSegmentId: not null,
+ parentServiceInstance: not null,
+ parentService: aio_consumer,
+ traceId: not null,
+ }
+ - serviceName: aio_consumer
+ segmentSize: 1
+ segments:
+ - segmentId: not null
+ spans:
+ - operationName: /example.Greeter/SayHello
+ parentSpanId: 0
+ spanId: 1
+ spanLayer: RPCFramework
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 23
+ isError: false
+ spanType: Exit
+ peer: aio_provider:50061
+ skipAnalysis: false
+ tags:
+ - { key: grpc.method, value: /example.Greeter/SayHello }
+ - { key: grpc.url, value: "aio_provider:50061" }
+ - operationName: /example.Greeter/SayHelloUS
+ parentSpanId: 0
+ spanId: 2
+ spanLayer: RPCFramework
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 23
+ isError: false
+ spanType: Exit
+ peer: aio_provider:50061
+ skipAnalysis: false
+ tags:
+ - { key: grpc.method, value: /example.Greeter/SayHelloUS }
+ - { key: grpc.url, value: "aio_provider:50061" }
+ - operationName: /example.Greeter/SayHelloSU
+ parentSpanId: 0
+ spanId: 3
+ spanLayer: RPCFramework
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 23
+ isError: false
+ spanType: Exit
+ peer: aio_provider:50061
+ skipAnalysis: false
+ tags:
+ - { key: grpc.method, value: /example.Greeter/SayHelloSU }
+ - { key: grpc.url, value: "aio_provider:50061" }
+ - operationName: /example.Greeter/SayHelloSS
+ parentSpanId: 0
+ spanId: 4
+ spanLayer: RPCFramework
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 23
+ isError: false
+ spanType: Exit
+ peer: aio_provider:50061
+ skipAnalysis: false
+ tags:
+ - { key: grpc.method, value: /example.Greeter/SayHelloSS }
+ - { key: grpc.url, value: "aio_provider:50061" }
+ - operationName: /
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Http
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 7000
+ isError: false
+ spanType: Entry
+ peer: not null
+ skipAnalysis: false
+ tags:
+ - { key: http.method, value: GET }
+ - { key: http.url, value: "http://127.0.0.1:50062/" }
+ - { key: http.status_code, value: "200" }
diff --git a/skywalking/meter/pvm/data_source.py
b/tests/plugin/web/sw_grpc/services/__init__.py
similarity index 73%
copy from skywalking/meter/pvm/data_source.py
copy to tests/plugin/web/sw_grpc/services/__init__.py
index 3f97c78..b1312a0 100644
--- a/skywalking/meter/pvm/data_source.py
+++ b/tests/plugin/web/sw_grpc/services/__init__.py
@@ -14,13 +14,3 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-
-from skywalking.meter.gauge import Gauge
-
-
-class DataSource:
- def register(self):
- for name in dir(self):
- if name.endswith('generator'):
- generator = getattr(self, name)()
- Gauge.Builder('instance_pvm_' + name[:-10], generator).build()
diff --git a/tests/plugin/web/sw_grpc/services/aio_consumer.py
b/tests/plugin/web/sw_grpc/services/aio_consumer.py
new file mode 100644
index 0000000..0b19fb4
--- /dev/null
+++ b/tests/plugin/web/sw_grpc/services/aio_consumer.py
@@ -0,0 +1,54 @@
+#
+# 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.
+#
+
+import asyncio
+import socketserver
+from http.server import BaseHTTPRequestHandler
+
+import example_pb2
+import example_pb2_grpc
+import grpc
+
+
+async def generate_messages():
+ yield example_pb2.HelloRequest(name='World')
+
+
+class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
+ def do_GET(self): # noqa
+ async def task():
+ async with grpc.aio.insecure_channel('aio_provider:50061') as
channel:
+ stub = example_pb2_grpc.GreeterStub(channel)
+ request = example_pb2.HelloRequest(name='World')
+ await stub.SayHello(request)
+ async for _ in stub.SayHelloUS(request):
+ pass
+ await stub.SayHelloSU(generate_messages())
+ async for _ in stub.SayHelloSS(generate_messages()):
+ pass
+
+ asyncio.run(task())
+ self.send_response(200)
+ self.end_headers()
+ self.wfile.write(b'Hello, world')
+
+
+if __name__ == '__main__':
+ PORT = 50062
+ with socketserver.TCPServer(('', PORT), SimpleHTTPRequestHandler) as httpd:
+ print('serving at port', PORT)
+ httpd.serve_forever()
diff --git a/tests/plugin/web/sw_grpc/services/aio_provider.py
b/tests/plugin/web/sw_grpc/services/aio_provider.py
new file mode 100644
index 0000000..5771e06
--- /dev/null
+++ b/tests/plugin/web/sw_grpc/services/aio_provider.py
@@ -0,0 +1,66 @@
+#
+# 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.
+#
+
+import asyncio
+from concurrent import futures
+from typing import Any, AsyncGenerator, AsyncIterable, Tuple
+
+import example_pb2
+import example_pb2_grpc
+import grpc
+
+
+async def async_enumerate(aiterable: AsyncIterable[Any], start: int = 0) ->
AsyncGenerator[Tuple[int, Any], Any]:
+ index = start
+ async for item in aiterable:
+ yield index, item
+ index += 1
+
+
+class GreeterServicer(example_pb2_grpc.GreeterServicer):
+ async def SayHello(self, request, context): # noqa
+ return example_pb2.HelloReply()
+
+ async def SayHelloUS(self, request, context): # noqa
+ for i in range(3):
+ response = example_pb2.HelloReply()
+ response.message = f'Hello, {request.name} {i}!'
+ yield response
+
+ async def SayHelloSU(self, request_iterator, context): # noqa
+ response = example_pb2.HelloReply()
+ async for request in request_iterator:
+ response.message = f'Hello, {request.name}!'
+ return response
+
+ async def SayHelloSS(self, request_iterator, context): # noqa
+ async for i, request in async_enumerate(request_iterator):
+ response = example_pb2.HelloReply()
+ response.message = f'Hello, {request.name} {i}!'
+ yield response
+
+
+async def serve():
+ server = grpc.aio.server(futures.ThreadPoolExecutor(max_workers=10))
+ example_pb2_grpc.add_GreeterServicer_to_server(GreeterServicer(), server)
+ server.add_insecure_port('[::]:50061')
+ await server.start()
+ await server.wait_for_termination()
+
+
+if __name__ == '__main__':
+ asyncio.run(serve())
diff --git a/tests/plugin/web/sw_grpc/services/consumer.py
b/tests/plugin/web/sw_grpc/services/consumer.py
new file mode 100644
index 0000000..765b2bb
--- /dev/null
+++ b/tests/plugin/web/sw_grpc/services/consumer.py
@@ -0,0 +1,50 @@
+#
+# 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.
+#
+
+import socketserver
+from http.server import BaseHTTPRequestHandler
+
+import example_pb2
+import example_pb2_grpc
+import grpc
+
+
+def generate_messages():
+ yield example_pb2.HelloRequest(name='World')
+
+
+class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
+ def do_GET(self): # noqa
+ with grpc.insecure_channel('provider:50051') as channel:
+ stub = example_pb2_grpc.GreeterStub(channel)
+ request = example_pb2.HelloRequest(name='World')
+ stub.SayHello(request)
+ for _ in stub.SayHelloUS(request):
+ pass
+ stub.SayHelloSU(generate_messages())
+ for _ in stub.SayHelloSS(generate_messages()):
+ pass
+ self.send_response(200)
+ self.end_headers()
+ self.wfile.write(b'Hello, world')
+
+
+if __name__ == '__main__':
+ PORT = 50052
+ with socketserver.TCPServer(('', PORT), SimpleHTTPRequestHandler) as httpd:
+ print('serving at port', PORT)
+ httpd.serve_forever()
diff --git a/tests/plugin/web/sw_grpc/services/provider.py
b/tests/plugin/web/sw_grpc/services/provider.py
new file mode 100644
index 0000000..0269868
--- /dev/null
+++ b/tests/plugin/web/sw_grpc/services/provider.py
@@ -0,0 +1,57 @@
+#
+# 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 concurrent import futures
+
+import example_pb2
+import example_pb2_grpc
+import grpc
+
+
+class GreeterServicer(example_pb2_grpc.GreeterServicer):
+ def SayHello(self, request, context): # noqa
+ return example_pb2.HelloReply()
+
+ def SayHelloUS(self, request, context): # noqa
+ for i in range(3):
+ response = example_pb2.HelloReply()
+ response.message = f'Hello, {request.name} {i}!'
+ yield response
+
+ def SayHelloSU(self, request_iterator, context): # noqa
+ response = example_pb2.HelloReply()
+ for request in request_iterator:
+ response.message = f'Hello, {request.name}!'
+ return response
+
+ def SayHelloSS(self, request_iterator, context): # noqa
+ for i, request in enumerate(request_iterator):
+ response = example_pb2.HelloReply()
+ response.message = f'Hello, {request.name} {i}!'
+ yield response
+
+
+def serve():
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+ example_pb2_grpc.add_GreeterServicer_to_server(GreeterServicer(), server)
+ server.add_insecure_port('[::]:50051')
+ server.start()
+ server.wait_for_termination()
+
+
+if __name__ == '__main__':
+ serve()
diff --git a/skywalking/meter/pvm/data_source.py
b/tests/plugin/web/sw_grpc/test_grpc.py
similarity index 53%
copy from skywalking/meter/pvm/data_source.py
copy to tests/plugin/web/sw_grpc/test_grpc.py
index 3f97c78..12d26ae 100644
--- a/skywalking/meter/pvm/data_source.py
+++ b/tests/plugin/web/sw_grpc/test_grpc.py
@@ -14,13 +14,30 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+from typing import Any, Callable
-from skywalking.meter.gauge import Gauge
+import pytest
+import requests
+from skywalking.plugins.sw_grpc import support_matrix
+from tests.orchestrator import get_test_vector
+from tests.plugin.base import TestPluginBase
-class DataSource:
- def register(self):
- for name in dir(self):
- if name.endswith('generator'):
- generator = getattr(self, name)()
- Gauge.Builder('instance_pvm_' + name[:-10], generator).build()
+
[email protected]
+def prepare() -> Callable[..., None]:
+
+ def f(*_: Any) -> None:
+ requests.get('http://127.0.0.1:50052/', timeout=5)
+ requests.get('http://127.0.0.1:50062/', timeout=5)
+
+ return f
+
+
+class TestPlugin(TestPluginBase):
+ @pytest.mark.parametrize('version', get_test_vector(lib_name='grpcio',
support_matrix=support_matrix))
+ def test_plugin(self, docker_compose, version):
+ import time
+
+ time.sleep(100)
+ self.validate()
diff --git a/tools/config_doc_gen.py b/tools/config_doc_gen.py
index 01e527f..9004b70 100644
--- a/tools/config_doc_gen.py
+++ b/tools/config_doc_gen.py
@@ -87,7 +87,7 @@ def create_entry(comment: str, config_index: int) -> str:
"""
def env_var_name(config_entry):
- return 'SW_' + config_entry.upper()
+ return f'SW_{config_entry.upper()}'
configuration = list(OPTIONS.keys())[config_index]
type_ = OPTIONS[configuration][1]