Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/en/setup/Plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ or a limitation of SkyWalking auto-instrumentation (welcome to contribute!)
| [sanic](https://sanic.readthedocs.io/en/latest) | Python >=3.10 - NOT SUPPORTED YET; Python >=3.7 - ['20.12']; | `sw_sanic` |
| [tornado](https://www.tornadoweb.org) | Python >=3.14 - ['6.4']; Python >=3.10 - ['6.0', '6.1']; | `sw_tornado` |
| [urllib3](https://urllib3.readthedocs.io/en/latest/) | Python >=3.12 - NOT SUPPORTED YET; Python >=3.10 - ['1.26', '1.25']; | `sw_urllib3` |
| [urllib3](https://urllib3.readthedocs.io/en/latest/) | Python >=3.12 - ['2.3', '2.0']; | `sw_urllib3_v2` |
| [urllib_request](https://docs.python.org/3/library/urllib.request.html) | Python >=3.7 - ['*']; | `sw_urllib_request` |
| [websockets](https://websockets.readthedocs.io) | Python >=3.7 - ['10.3', '10.4']; | `sw_websockets` |
### Notes
Expand All @@ -58,6 +59,8 @@ Hug is believed to be abandoned project, use this plugin with a bit more caution
Instead of Hug, plugin test should move to test actual Falcon.
- The Neo4j plugin integrates neo4j python driver 5.x.x versions which
support both Neo4j 5 and 4.4 DBMS.
- urllib3 1.x plugin. For urllib3 2.x, see sw_urllib3_v2.
- urllib3 2.x plugin. For urllib3 1.x, see sw_urllib3.
- The websocket instrumentation only traces client side connection handshake,
the actual message exchange (send/recv) is not traced since injecting headers to socket message
body is the only way to propagate the trace context, which requires customization of message structure
Expand Down
4 changes: 2 additions & 2 deletions skywalking/plugins/sw_urllib3.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
link_vector = ['https://urllib3.readthedocs.io/en/latest/']
support_matrix = {
'urllib3': {
'>=3.12': [], # urllib3 2.x removed urllib3.request.RequestMethods, plugin needs adaptation
'>=3.12': [], # urllib3 1.x can't install on 3.12+, see sw_urllib3_v2 for 2.x
'>=3.10': ['1.26', '1.25'],
}
}
note = """"""
note = """urllib3 1.x plugin. For urllib3 2.x, see sw_urllib3_v2."""


def install():
Expand Down
77 changes: 77 additions & 0 deletions skywalking/plugins/sw_urllib3_v2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#
# 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, config
from skywalking.trace.context import get_context, NoopContext
from skywalking.trace.span import NoopSpan
from skywalking.trace.tags import TagHttpMethod, TagHttpURL, TagHttpStatusCode

link_vector = ['https://urllib3.readthedocs.io/en/latest/']
support_matrix = {
'urllib3': {
'>=3.12': ['2.3', '2.0'],
}
}
note = """urllib3 2.x plugin. For urllib3 1.x, see sw_urllib3."""


def install():
from urllib3 import PoolManager

# urllib3 2.x removed RequestMethods base class;
# PoolManager.request is the direct entry point.
# Guard: if RequestMethods still exists, this is urllib3 1.x — let sw_urllib3 handle it.
try:
from urllib3.request import RequestMethods # noqa: F401
return # urllib3 1.x detected, skip — sw_urllib3 handles it
except ImportError:
pass # urllib3 2.x, proceed

_request = PoolManager.request

def _sw_request(this: PoolManager, method, url, body=None, fields=None, headers=None, json=None, **urlopen_kw):
from skywalking.utils.filter import sw_urlparse

url_param = sw_urlparse(url)

span = NoopSpan(NoopContext()) if config.ignore_http_method_check(method) \
else get_context().new_exit_span(op=url_param.path or '/', peer=url_param.netloc,
component=Component.Urllib3)

with span:
carrier = span.inject()
span.layer = Layer.Http

if headers is None:
headers = {}
else:
headers = dict(headers)
for item in carrier:
headers[item.key] = item.val

span.tag(TagHttpMethod(method.upper()))
span.tag(TagHttpURL(url_param.geturl()))

res = _request(this, method, url, body=body, fields=fields, headers=headers, json=json, **urlopen_kw)

span.tag(TagHttpStatusCode(res.status))
if res.status >= 400:
span.error_occurred = True

return res

PoolManager.request = _sw_request
9 changes: 7 additions & 2 deletions tests/plugin/http/sw_urllib3/test_urllib3.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@
import pytest
import requests

from skywalking.plugins.sw_urllib3 import support_matrix
from skywalking.plugins.sw_urllib3 import support_matrix as v1_matrix
from skywalking.plugins.sw_urllib3_v2 import support_matrix as v2_matrix
from tests.orchestrator import get_test_vector
from tests.plugin.base import TestPluginBase

# Merge v1 and v2 test vectors — get_test_vector returns versions for the current Python
_versions = (get_test_vector(lib_name='urllib3', support_matrix=v1_matrix)
+ get_test_vector(lib_name='urllib3', support_matrix=v2_matrix))


@pytest.fixture
def prepare():
Expand All @@ -31,6 +36,6 @@ def prepare():


class TestPlugin(TestPluginBase):
@pytest.mark.parametrize('version', get_test_vector(lib_name='urllib3', support_matrix=support_matrix))
@pytest.mark.parametrize('version', _versions)
def test_plugin(self, docker_compose, version):
self.validate()
Loading