Urllib3 request hook (#660)

* Urllib3: extend request hook with request body and headers

* Change GET to POST in test_extended_request_hook

* added changelog entry

* update ExtendedReqeustHookT

* adding up to date generated code

* replace _RequestHookT with _ExtendedRequestHookT

* updated Changelog

Co-authored-by: Ran Nozik <ran@heliosphere.io>
This commit is contained in:
ItayGibel-heliosphere
2021-09-13 20:28:59 +03:00
committed by GitHub
parent fc8a02bcf8
commit b47328e134
3 changed files with 46 additions and 4 deletions

View File

@ -15,6 +15,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `opentelemetry-instrumentation-botocore` Fix span injection for lambda invoke
([#663](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/663))
### Changed
- `opentelemetry-instrumentation-urllib3` Updated `_RequestHookT` with two additional fields - the request body and the request headers
([#660](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/660))
## [1.5.0-0.24b0](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v1.5.0-0.24b0) - 2021-08-26
### Added

View File

@ -90,7 +90,15 @@ _SUPPRESS_HTTP_INSTRUMENTATION_KEY = context.create_key(
_UrlFilterT = typing.Optional[typing.Callable[[str], str]]
_RequestHookT = typing.Optional[
typing.Callable[[Span, urllib3.connectionpool.HTTPConnectionPool], None]
typing.Callable[
[
Span,
urllib3.connectionpool.HTTPConnectionPool,
typing.Dict,
typing.Optional[str],
],
None,
]
]
_ResponseHookT = typing.Optional[
typing.Callable[
@ -150,6 +158,7 @@ def _instrument(
method = _get_url_open_arg("method", args, kwargs).upper()
url = _get_url(instance, args, kwargs, url_filter)
headers = _prepare_headers(kwargs)
body = _get_url_open_arg("body", args, kwargs)
span_name = "HTTP {}".format(method.strip())
span_attributes = {
@ -161,7 +170,7 @@ def _instrument(
span_name, kind=SpanKind.CLIENT, attributes=span_attributes
) as span:
if callable(request_hook):
request_hook(span, instance)
request_hook(span, instance, headers, body)
inject(headers)
with _suppress_further_instrumentation():

View File

@ -11,7 +11,7 @@
# 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
import typing
from unittest import mock
@ -45,6 +45,7 @@ class TestURLLib3Instrumentor(TestBase):
httpretty.enable(allow_net_connect=False)
httpretty.register_uri(httpretty.GET, self.HTTP_URL, body="Hello!")
httpretty.register_uri(httpretty.GET, self.HTTPS_URL, body="Hello!")
httpretty.register_uri(httpretty.POST, self.HTTP_URL, body="Hello!")
def tearDown(self):
super().tearDown()
@ -261,7 +262,7 @@ class TestURLLib3Instrumentor(TestBase):
self.assert_success_span(response, self.HTTP_URL)
def test_hooks(self):
def request_hook(span, request):
def request_hook(span, request, body, headers):
span.update_name("name set from hook")
def response_hook(span, request, response):
@ -279,3 +280,30 @@ class TestURLLib3Instrumentor(TestBase):
self.assertEqual(span.name, "name set from hook")
self.assertIn("response_hook_attr", span.attributes)
self.assertEqual(span.attributes["response_hook_attr"], "value")
def test_request_hook_params(self):
def request_hook(span, request, headers, body):
span.set_attribute("request_hook_headers", json.dumps(headers))
span.set_attribute("request_hook_body", body)
URLLib3Instrumentor().uninstrument()
URLLib3Instrumentor().instrument(request_hook=request_hook,)
headers = {"header1": "value1", "header2": "value2"}
body = "param1=1&param2=2"
pool = urllib3.HTTPConnectionPool("httpbin.org")
response = pool.request(
"POST", "/status/200", body=body, headers=headers
)
self.assertEqual(b"Hello!", response.data)
span = self.assert_span()
self.assertIn("request_hook_headers", span.attributes)
self.assertEqual(
span.attributes["request_hook_headers"], json.dumps(headers)
)
self.assertIn("request_hook_body", span.attributes)
self.assertEqual(span.attributes["request_hook_body"], body)