未验证 提交 a59a8dd2 编写于 作者: H huawei 提交者: GitHub

[Plugin] Add plugin for urllib3 library (#69)

Co-authored-by: Nkezhenxu94 <kezhenxu94@163.com>
上级 c7339854
......@@ -14,5 +14,6 @@ Library | Versions | Plugin Name
| [pika](https://pika.readthedocs.io/en/stable/) | 1.1.0 | `sw_rabbitmq` |
| [pymongo](https://pymongo.readthedocs.io/en/stable/) | 3.11.0 | `sw_pymongo` |
| [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` |
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.
......@@ -36,6 +36,7 @@ class Component(Enum):
RabbitmqProducer = 52
RabbitmqConsumer = 53
Elasticsearch = 47
Urllib3 = 7006
class Layer(Enum):
......
#
# 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 logging
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
logger = logging.getLogger(__name__)
def install():
# noinspection PyBroadException
try:
from urllib3.request import RequestMethods
_request = RequestMethods.request
def _sw_request(this: RequestMethods, method, url, fields=None, headers=None, **urlopen_kw):
from urllib.parse import urlparse
url_param = urlparse(url)
carrier = Carrier()
context = get_context()
with context.new_exit_span(op=url_param.path or "/", peer=url_param.netloc, carrier=carrier) as span:
span.layer = Layer.Http
span.component = Component.Urllib3
if headers is None:
headers = {}
for item in carrier:
headers[item.key] = item.val
else:
for item in carrier:
headers[item.key] = item.val
try:
res = _request(this, method, url, fields=fields, headers=headers, **urlopen_kw)
span.tag(Tag(key=tags.HttpMethod, val=method.upper()))
span.tag(Tag(key=tags.HttpUrl, val=url))
span.tag(Tag(key=tags.HttpStatus, val=res.status))
if res.status >= 400:
span.error_occurred = True
except BaseException as e:
span.raised()
raise e
return res
RequestMethods.request = _sw_request
except Exception:
logger.warning('failed to install plugin %s', __name__)
#
# 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.
#
#
# 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 flask && 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 flask && pip install -r /app/requirements.txt && python3 /app/services/consumer.py']
depends_on:
collector:
condition: service_healthy
provider:
condition: service_healthy
networks:
beyond:
#
# 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: /users
operationId: 0
parentSpanId: -1
spanId: 0
spanLayer: Http
tags:
- key: http.method
value: POST
- key: url
value: http://provider:9091/users
- key: status.code
value: '200'
refs:
- parentEndpoint: /users
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: 7001
spanType: Entry
peer: not null
skipAnalysis: false
- serviceName: consumer
segmentSize: 1
segments:
- segmentId: not null
spans:
- operationName: /users
operationId: 0
parentSpanId: 0
spanId: 1
spanLayer: Http
startTime: gt 0
endTime: gt 0
componentId: 7006
isError: false
spanType: Exit
peer: not null
skipAnalysis: false
tags:
- key: http.method
value: POST
- key: url
value: 'http://provider:9091/users'
- key: status.code
value: '200'
- operationName: /users
operationId: 0
parentSpanId: -1
spanId: 0
spanLayer: Http
startTime: gt 0
endTime: gt 0
componentId: 7001
isError: false
spanType: Entry
peer: not null
skipAnalysis: false
tags:
- key: http.method
value: GET
- key: url
value: 'http://0.0.0.0:9090/users'
- key: status.code
value: '200'
\ No newline at end of file
#
# 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.
#
#
# 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 json
from skywalking import agent, config
if __name__ == '__main__':
config.service_name = 'consumer'
config.logging_level = 'DEBUG'
agent.start()
from flask import Flask, jsonify
app = Flask(__name__)
import urllib3
@app.route("/users", methods=["POST", "GET"])
def application():
http = urllib3.PoolManager()
res = http.request("POST", "http://provider:9091/users")
return jsonify(json.loads(res.data.decode('utf-8')))
PORT = 9090
app.run(host='0.0.0.0', port=PORT, debug=True)
#
# 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 time
from skywalking import agent, config
if __name__ == '__main__':
config.service_name = 'provider'
config.logging_level = 'DEBUG'
agent.start()
from flask import Flask, jsonify
app = Flask(__name__)
@app.route("/users", methods=["POST", "GET"])
def application():
time.sleep(0.5)
return jsonify({"song": "Despacito", "artist": "Luis Fonsi"})
PORT = 9091
app.run(host='0.0.0.0', port=PORT, debug=True)
#
# 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/users')
class TestPlugin(TestPluginBase):
@pytest.mark.parametrize('version', [
'urllib3==1.25.10',
'urllib3==1.25.9'
])
def test_plugin(self, docker_compose, version):
self.validate()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册