Files
2021-09-27 10:21:26 -07:00

134 lines
4.8 KiB
Python

# Copyright The OpenTelemetry Authors
#
# Licensed 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 http.client import HTTPConnection, HTTPResponse, HTTPSConnection
from opentelemetry import trace
from opentelemetry.test.httptest import HttpTestBase
from opentelemetry.test.test_base import TestBase
from opentelemetry.trace.span import INVALID_SPAN
from opentelemetry.util.http.httplib import (
HttpClientInstrumentor,
set_ip_on_next_http_connection,
)
# pylint: disable=too-many-public-methods
class TestHttpBase(TestBase, HttpTestBase):
def setUp(self):
super().setUp()
HttpClientInstrumentor().instrument()
self.server_thread, self.server = self.run_server()
def tearDown(self):
HttpClientInstrumentor().uninstrument()
self.server.shutdown()
self.server_thread.join()
super().tearDown()
def assert_span(self, exporter=None, num_spans=1):
if exporter is None:
exporter = self.memory_exporter
span_list = exporter.get_finished_spans()
self.assertEqual(num_spans, len(span_list))
if num_spans == 0:
return None
if num_spans == 1:
return span_list[0]
return span_list
def test_basic(self):
resp, body = self.perform_request()
assert resp.status == 200
assert body == b"Hello!"
self.assert_span(num_spans=0)
def test_basic_with_span(self):
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span(
"HTTP GET"
) as span, set_ip_on_next_http_connection(span):
resp, body = self.perform_request()
assert resp.status == 200
assert body == b"Hello!"
span = self.assert_span(num_spans=1)
self.assertEqual(span.attributes, {"net.peer.ip": "127.0.0.1"})
def test_with_nested_span(self):
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span(
"requests HTTP GET"
) as span, set_ip_on_next_http_connection(span):
with tracer.start_as_current_span(
"urllib3 HTTP GET"
) as span2, set_ip_on_next_http_connection(span2):
resp, body = self.perform_request()
assert resp.status == 200
assert body == b"Hello!"
for span in self.assert_span(num_spans=2):
self.assertEqual(span.attributes, {"net.peer.ip": "127.0.0.1"})
def test_with_nested_nonrecording_span(self):
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span(
"requests HTTP GET"
) as span, set_ip_on_next_http_connection(span):
with trace.use_span(INVALID_SPAN), set_ip_on_next_http_connection(
INVALID_SPAN
):
resp, body = self.perform_request()
assert resp.status == 200
assert body == b"Hello!"
span = self.assert_span(num_spans=1)
self.assertEqual(span.attributes, {"net.peer.ip": "127.0.0.1"})
def test_with_only_nonrecording_span(self):
with trace.use_span(INVALID_SPAN), set_ip_on_next_http_connection(
INVALID_SPAN
):
resp, body = self.perform_request()
assert resp.status == 200
assert body == b"Hello!"
self.assert_span(num_spans=0)
def perform_request(self, secure=False) -> HTTPResponse:
conn_cls = HTTPSConnection if secure else HTTPConnection
conn = conn_cls(self.server.server_address[0], self.server.server_port)
resp = None
try:
conn.request("GET", "/", headers={"Connection": "close"})
resp = conn.getresponse()
return resp, resp.read()
finally:
if resp:
resp.close()
conn.close()
def test_uninstrument(self):
HttpClientInstrumentor().uninstrument()
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span(
"HTTP GET"
) as span, set_ip_on_next_http_connection(span):
body = self.perform_request()[1]
self.assertEqual(b"Hello!", body)
# We should have a span, but it should have no attributes
self.assertFalse(self.assert_span(num_spans=1).attributes)
# instrument again to avoid warning message on tearDown
HttpClientInstrumentor().instrument()