You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ke...@apache.org on 2020/12/16 09:47:34 UTC
[skywalking-python] branch master updated: [Plugin] added pyramid
plugin (#102)
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 f7f5aa7 [Plugin] added pyramid plugin (#102)
f7f5aa7 is described below
commit f7f5aa77ace3f640fed3acaed9b7325a72c40a35
Author: Tomasz Pytel <to...@gmail.com>
AuthorDate: Wed Dec 16 06:47:28 2020 -0300
[Plugin] added pyramid plugin (#102)
* add test case
Co-authored-by: kezhenxu94 <ke...@apache.org>
---
docs/Plugins.md | 2 +
requirements.txt | 1 +
skywalking/__init__.py | 1 +
skywalking/plugins/sw_pyramid.py | 56 +++++++++++++++++
tests/plugin/sw_pyramid/__init__.py | 16 +++++
tests/plugin/sw_pyramid/docker-compose.yml | 60 ++++++++++++++++++
tests/plugin/sw_pyramid/expected.data.yml | 92 ++++++++++++++++++++++++++++
tests/plugin/sw_pyramid/services/__init__.py | 16 +++++
tests/plugin/sw_pyramid/services/consumer.py | 47 ++++++++++++++
tests/plugin/sw_pyramid/services/provider.py | 49 +++++++++++++++
tests/plugin/sw_pyramid/test_plugin.py | 37 +++++++++++
11 files changed, 377 insertions(+)
diff --git a/docs/Plugins.md b/docs/Plugins.md
index 4deeb33..3a3bc24 100644
--- a/docs/Plugins.md
+++ b/docs/Plugins.md
@@ -16,5 +16,7 @@ Library | Versions | Plugin Name
| [elasticsearch](https://github.com/elastic/elasticsearch-py) | 7.9.0 | `sw_elasticsearch` |
| [urllib3](https://urllib3.readthedocs.io/en/latest/) | >= 1.25.9 <= 1.25.10 | `sw_urllib3` |
| [sanic](https://sanic.readthedocs.io/en/latest/) | >= 20.3.0 <= 20.9.1 | `sw_sanic` |
+| [aiohttp](https://sanic.readthedocs.io/en/latest/) | >= 3.7.3 | `sw_aiohttp` |
+| [pyramid](https://trypyramid.com) | >= 1.9 | `sw_pyramid` |
The column `Versions` only indicates that the versions are tested, if you found the newer versions are also supported, welcome to add the newer version into the table.
diff --git a/requirements.txt b/requirements.txt
index eeea0d2..c0ccf07 100755
--- a/requirements.txt
+++ b/requirements.txt
@@ -38,6 +38,7 @@ py==1.9.0
pymongo==3.11.0
PyMySQL==0.10.0
pyparsing==2.4.7
+pyramid==1.10.5
pytest==6.0.1
pytz==2020.1
PyYAML==5.3.1
diff --git a/skywalking/__init__.py b/skywalking/__init__.py
index 7be2e43..eb180f1 100644
--- a/skywalking/__init__.py
+++ b/skywalking/__init__.py
@@ -39,6 +39,7 @@ class Component(Enum):
Urllib3 = 7006
Sanic = 7007
AioHttp = 7008
+ Pyramid = 7009
class Layer(Enum):
diff --git a/skywalking/plugins/sw_pyramid.py b/skywalking/plugins/sw_pyramid.py
new file mode 100644
index 0000000..6d27b00
--- /dev/null
+++ b/skywalking/plugins/sw_pyramid.py
@@ -0,0 +1,56 @@
+#
+# 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 skywalking import Layer, Component
+from skywalking.trace import tags
+from skywalking.trace.carrier import Carrier
+from skywalking.trace.context import get_context
+from skywalking.trace.tags import Tag
+
+
+def install():
+ from pyramid.router import Router
+
+ def _sw_invoke_request(self, request, *args, **kwargs):
+ context = get_context()
+ carrier = Carrier()
+
+ for item in carrier:
+ val = request.headers.get(item.key)
+
+ if val is not None:
+ item.val = val
+
+ with context.new_entry_span(op=request.path, carrier=carrier) as span:
+ span.layer = Layer.Http
+ span.component = Component.Pyramid
+ span.peer = request.remote_host or request.remote_addr
+
+ span.tag(Tag(key=tags.HttpMethod, val=request.method))
+ span.tag(Tag(key=tags.HttpUrl, val=str(request.url)))
+
+ resp = _invoke_request(self, request, *args, **kwargs)
+
+ span.tag(Tag(key=tags.HttpStatus, val=resp.status_code, overridable=True))
+
+ if resp.status_code >= 400:
+ span.error_occurred = True
+
+ return resp
+
+ _invoke_request = Router.invoke_request
+ Router.invoke_request = _sw_invoke_request
diff --git a/tests/plugin/sw_pyramid/__init__.py b/tests/plugin/sw_pyramid/__init__.py
new file mode 100644
index 0000000..b1312a0
--- /dev/null
+++ b/tests/plugin/sw_pyramid/__init__.py
@@ -0,0 +1,16 @@
+#
+# 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.
+#
diff --git a/tests/plugin/sw_pyramid/docker-compose.yml b/tests/plugin/sw_pyramid/docker-compose.yml
new file mode 100644
index 0000000..db53dcd
--- /dev/null
+++ b/tests/plugin/sw_pyramid/docker-compose.yml
@@ -0,0 +1,60 @@
+#
+# 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/docker-compose.base.yml
+
+ provider:
+ extends:
+ service: agent
+ file: ../docker/docker-compose.base.yml
+ ports:
+ - 9091:9091
+ volumes:
+ - .:/app
+ command: ['bash', '-c', 'pip install -r /app/requirements.txt && 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/9091"]
+ interval: 5s
+ timeout: 60s
+ retries: 120
+
+ consumer:
+ extends:
+ service: agent
+ file: ../docker/docker-compose.base.yml
+ ports:
+ - 9090:9090
+ volumes:
+ - .:/app
+ command: ['bash', '-c', 'pip install -r /app/requirements.txt && python3 /app/services/consumer.py']
+ depends_on:
+ collector:
+ condition: service_healthy
+ provider:
+ condition: service_healthy
+
+networks:
+ beyond:
diff --git a/tests/plugin/sw_pyramid/expected.data.yml b/tests/plugin/sw_pyramid/expected.data.yml
new file mode 100644
index 0000000..2977223
--- /dev/null
+++ b/tests/plugin/sw_pyramid/expected.data.yml
@@ -0,0 +1,92 @@
+#
+# 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: 1
+ segments:
+ - segmentId: not null
+ spans:
+ - operationName: /pyramid
+ operationId: 0
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Http
+ tags:
+ - key: http.method
+ value: POST
+ - key: url
+ value: http://provider:9091/pyramid
+ - key: status.code
+ value: '200'
+ refs:
+ - parentEndpoint: /pyramid
+ networkAddress: provider:9091
+ refType: CrossProcess
+ parentSpanId: 1
+ parentTraceSegmentId: not null
+ parentServiceInstance: not null
+ parentService: consumer
+ traceId: not null
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 7009
+ spanType: Entry
+ peer: not null
+ skipAnalysis: false
+ - serviceName: consumer
+ segmentSize: 1
+ segments:
+ - segmentId: not null
+ spans:
+ - operationName: /pyramid
+ operationId: 0
+ parentSpanId: 0
+ spanId: 1
+ spanLayer: Http
+ tags:
+ - key: http.method
+ value: POST
+ - key: url
+ value: http://provider:9091/pyramid
+ - key: status.code
+ value: '200'
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 7000
+ spanType: Exit
+ peer: provider:9091
+ skipAnalysis: false
+ - operationName: /pyramid
+ operationId: 0
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Http
+ tags:
+ - key: http.method
+ value: GET
+ - key: url
+ value: http://0.0.0.0:9090/pyramid
+ - key: status.code
+ value: '200'
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 7009
+ spanType: Entry
+ peer: not null
+ skipAnalysis: false
+
diff --git a/tests/plugin/sw_pyramid/services/__init__.py b/tests/plugin/sw_pyramid/services/__init__.py
new file mode 100644
index 0000000..b1312a0
--- /dev/null
+++ b/tests/plugin/sw_pyramid/services/__init__.py
@@ -0,0 +1,16 @@
+#
+# 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.
+#
diff --git a/tests/plugin/sw_pyramid/services/consumer.py b/tests/plugin/sw_pyramid/services/consumer.py
new file mode 100644
index 0000000..0aaf1e3
--- /dev/null
+++ b/tests/plugin/sw_pyramid/services/consumer.py
@@ -0,0 +1,47 @@
+#
+# 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 urllib import request
+from wsgiref.simple_server import make_server
+
+from pyramid.config import Configurator
+from pyramid.response import Response
+
+from skywalking import agent, config
+
+
+def index(req):
+ data = '{"name": "whatever"}'.encode('utf8')
+ req = request.Request(f'http://provider:9091/{req.path.lstrip("/")}')
+ req.add_header('Content-Type', 'application/json; charset=utf-8')
+ req.add_header('Content-Length', str(len(data)))
+ with request.urlopen(req, data):
+ return Response(data)
+
+
+if __name__ == '__main__':
+ config.service_name = 'consumer'
+ agent.start()
+
+ with Configurator() as config:
+ config.add_route('pyramid', '/pyramid')
+ config.add_view(index, route_name='pyramid')
+
+ app = config.make_wsgi_app()
+
+ server = make_server('0.0.0.0', 9090, app)
+
+ server.serve_forever()
diff --git a/tests/plugin/sw_pyramid/services/provider.py b/tests/plugin/sw_pyramid/services/provider.py
new file mode 100644
index 0000000..485da47
--- /dev/null
+++ b/tests/plugin/sw_pyramid/services/provider.py
@@ -0,0 +1,49 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+from wsgiref.simple_server import make_server
+
+from pyramid.config import Configurator
+from pyramid.response import Response
+
+from skywalking import agent, config
+
+
+def index(request):
+ return Response('Hello World!')
+
+
+def error(request):
+ raise Exception('Error!')
+
+
+if __name__ == '__main__':
+ config.service_name = 'provider'
+ config.logging_level = 'DEBUG'
+ agent.start()
+
+ with Configurator() as config:
+ config.add_route('pyramid', '/pyramid')
+ config.add_route('error', '/error')
+ config.add_view(index, route_name='pyramid')
+ config.add_view(error, route_name='error')
+
+ app = config.make_wsgi_app()
+
+ server = make_server('0.0.0.0', 9091, app)
+
+ server.serve_forever()
diff --git a/tests/plugin/sw_pyramid/test_plugin.py b/tests/plugin/sw_pyramid/test_plugin.py
new file mode 100644
index 0000000..6aa822f
--- /dev/null
+++ b/tests/plugin/sw_pyramid/test_plugin.py
@@ -0,0 +1,37 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+from typing import Callable
+
+import pytest
+import requests
+
+from tests.plugin.base import TestPluginBase
+
+
+@pytest.fixture
+def prepare():
+ # type: () -> Callable
+ return lambda *_: requests.get('http://0.0.0.0:9090/pyramid')
+
+
+class TestPlugin(TestPluginBase):
+ @pytest.mark.parametrize('version', [
+ 'pyramid==1.10',
+ 'pyramid==1.9',
+ ])
+ def test_plugin(self, docker_compose, version):
+ self.validate()