mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-07-30 13:43:03 +08:00
Change metrics test to work with base_test.py (#1688)
This commit is contained in:
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -6,7 +6,7 @@ on:
|
|||||||
- 'release/*'
|
- 'release/*'
|
||||||
pull_request:
|
pull_request:
|
||||||
env:
|
env:
|
||||||
CORE_REPO_SHA: d0bb12b34b0c487198c935001636b6163485a50f
|
CORE_REPO_SHA: 2d1f0b9f5fce62549d1338882f37b91b95881c75
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
@ -15,97 +15,23 @@
|
|||||||
|
|
||||||
from timeit import default_timer
|
from timeit import default_timer
|
||||||
|
|
||||||
from tornado.testing import AsyncHTTPTestCase
|
|
||||||
|
|
||||||
from opentelemetry import trace
|
|
||||||
from opentelemetry.instrumentation.tornado import TornadoInstrumentor
|
from opentelemetry.instrumentation.tornado import TornadoInstrumentor
|
||||||
from opentelemetry.sdk.metrics.export import (
|
from opentelemetry.sdk.metrics.export import HistogramDataPoint
|
||||||
HistogramDataPoint,
|
|
||||||
NumberDataPoint,
|
from .test_instrumentation import ( # pylint: disable=no-name-in-module,import-error
|
||||||
|
TornadoTest,
|
||||||
)
|
)
|
||||||
from opentelemetry.test.test_base import TestBase
|
|
||||||
|
|
||||||
from .tornado_test_app import make_app
|
|
||||||
|
|
||||||
|
|
||||||
class TornadoTest(AsyncHTTPTestCase, TestBase):
|
class TestTornadoMetricsInstrumentation(TornadoTest):
|
||||||
# pylint:disable=no-self-use
|
# Return Sequence with one histogram
|
||||||
def get_app(self):
|
def create_histogram_data_points(self, sum_data_point, attributes):
|
||||||
tracer = trace.get_tracer(__name__)
|
return [
|
||||||
app = make_app(tracer)
|
self.create_histogram_data_point(
|
||||||
return app
|
sum_data_point, 1, sum_data_point, sum_data_point, attributes
|
||||||
|
|
||||||
def get_sorted_metrics(self):
|
|
||||||
resource_metrics = (
|
|
||||||
self.memory_metrics_reader.get_metrics_data().resource_metrics
|
|
||||||
)
|
|
||||||
for metrics in resource_metrics:
|
|
||||||
for scope_metrics in metrics.scope_metrics:
|
|
||||||
all_metrics = list(scope_metrics.metrics)
|
|
||||||
return self.sorted_metrics(all_metrics)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def sorted_metrics(metrics):
|
|
||||||
"""
|
|
||||||
Sorts metrics by metric name.
|
|
||||||
"""
|
|
||||||
return sorted(
|
|
||||||
metrics,
|
|
||||||
key=lambda m: m.name,
|
|
||||||
)
|
|
||||||
|
|
||||||
def assert_metric_expected(
|
|
||||||
self, metric, expected_value, expected_attributes
|
|
||||||
):
|
|
||||||
data_point = next(iter(metric.data.data_points))
|
|
||||||
|
|
||||||
if isinstance(data_point, HistogramDataPoint):
|
|
||||||
self.assertEqual(
|
|
||||||
data_point.sum,
|
|
||||||
expected_value,
|
|
||||||
)
|
|
||||||
elif isinstance(data_point, NumberDataPoint):
|
|
||||||
self.assertEqual(
|
|
||||||
data_point.value,
|
|
||||||
expected_value,
|
|
||||||
)
|
)
|
||||||
|
]
|
||||||
|
|
||||||
self.assertDictEqual(
|
|
||||||
expected_attributes,
|
|
||||||
dict(data_point.attributes),
|
|
||||||
)
|
|
||||||
|
|
||||||
def assert_duration_metric_expected(
|
|
||||||
self, metric, duration_estimated, expected_attributes
|
|
||||||
):
|
|
||||||
data_point = next(iter(metric.data.data_points))
|
|
||||||
|
|
||||||
self.assertAlmostEqual(
|
|
||||||
data_point.sum,
|
|
||||||
duration_estimated,
|
|
||||||
delta=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertDictEqual(
|
|
||||||
expected_attributes,
|
|
||||||
dict(data_point.attributes),
|
|
||||||
)
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super().setUp()
|
|
||||||
TornadoInstrumentor().instrument(
|
|
||||||
server_request_hook=getattr(self, "server_request_hook", None),
|
|
||||||
client_request_hook=getattr(self, "client_request_hook", None),
|
|
||||||
client_response_hook=getattr(self, "client_response_hook", None),
|
|
||||||
meter_provider=self.meter_provider,
|
|
||||||
)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
TornadoInstrumentor().uninstrument()
|
|
||||||
super().tearDown()
|
|
||||||
|
|
||||||
|
|
||||||
class TestTornadoInstrumentor(TornadoTest):
|
|
||||||
def test_basic_metrics(self):
|
def test_basic_metrics(self):
|
||||||
start_time = default_timer()
|
start_time = default_timer()
|
||||||
response = self.fetch("/")
|
response = self.fetch("/")
|
||||||
@ -132,42 +58,51 @@ class TestTornadoInstrumentor(TornadoTest):
|
|||||||
)
|
)
|
||||||
self.assert_metric_expected(
|
self.assert_metric_expected(
|
||||||
server_active_request,
|
server_active_request,
|
||||||
0,
|
[
|
||||||
{
|
self.create_number_data_point(
|
||||||
"http.method": "GET",
|
0,
|
||||||
"http.flavor": "HTTP/1.1",
|
attributes={
|
||||||
"http.scheme": "http",
|
"http.method": "GET",
|
||||||
"http.target": "/",
|
"http.flavor": "HTTP/1.1",
|
||||||
"http.host": response.request.headers["host"],
|
"http.scheme": "http",
|
||||||
},
|
"http.target": "/",
|
||||||
|
"http.host": response.request.headers["host"],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(server_duration.name, "http.server.duration")
|
self.assertEqual(server_duration.name, "http.server.duration")
|
||||||
self.assert_duration_metric_expected(
|
self.assert_metric_expected(
|
||||||
server_duration,
|
server_duration,
|
||||||
client_duration_estimated,
|
self.create_histogram_data_points(
|
||||||
{
|
client_duration_estimated,
|
||||||
"http.status_code": response.code,
|
attributes={
|
||||||
"http.method": "GET",
|
"http.method": "GET",
|
||||||
"http.flavor": "HTTP/1.1",
|
"http.flavor": "HTTP/1.1",
|
||||||
"http.scheme": "http",
|
"http.scheme": "http",
|
||||||
"http.target": "/",
|
"http.target": "/",
|
||||||
"http.host": response.request.headers["host"],
|
"http.host": response.request.headers["host"],
|
||||||
},
|
"http.status_code": response.code,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
est_value_delta=200,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(server_request_size.name, "http.server.request.size")
|
self.assertEqual(server_request_size.name, "http.server.request.size")
|
||||||
self.assert_metric_expected(
|
self.assert_metric_expected(
|
||||||
server_request_size,
|
server_request_size,
|
||||||
0,
|
self.create_histogram_data_points(
|
||||||
{
|
0,
|
||||||
"http.status_code": 200,
|
attributes={
|
||||||
"http.method": "GET",
|
"http.status_code": 200,
|
||||||
"http.flavor": "HTTP/1.1",
|
"http.method": "GET",
|
||||||
"http.scheme": "http",
|
"http.flavor": "HTTP/1.1",
|
||||||
"http.target": "/",
|
"http.scheme": "http",
|
||||||
"http.host": response.request.headers["host"],
|
"http.target": "/",
|
||||||
},
|
"http.host": response.request.headers["host"],
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -175,37 +110,44 @@ class TestTornadoInstrumentor(TornadoTest):
|
|||||||
)
|
)
|
||||||
self.assert_metric_expected(
|
self.assert_metric_expected(
|
||||||
server_response_size,
|
server_response_size,
|
||||||
len(response.body),
|
self.create_histogram_data_points(
|
||||||
{
|
len(response.body),
|
||||||
"http.status_code": response.code,
|
attributes={
|
||||||
"http.method": "GET",
|
"http.status_code": response.code,
|
||||||
"http.flavor": "HTTP/1.1",
|
"http.method": "GET",
|
||||||
"http.scheme": "http",
|
"http.flavor": "HTTP/1.1",
|
||||||
"http.target": "/",
|
"http.scheme": "http",
|
||||||
"http.host": response.request.headers["host"],
|
"http.target": "/",
|
||||||
},
|
"http.host": response.request.headers["host"],
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(client_duration.name, "http.client.duration")
|
self.assertEqual(client_duration.name, "http.client.duration")
|
||||||
self.assert_duration_metric_expected(
|
self.assert_metric_expected(
|
||||||
client_duration,
|
client_duration,
|
||||||
client_duration_estimated,
|
self.create_histogram_data_points(
|
||||||
{
|
client_duration_estimated,
|
||||||
"http.status_code": response.code,
|
attributes={
|
||||||
"http.method": "GET",
|
"http.status_code": response.code,
|
||||||
"http.url": response.effective_url,
|
"http.method": "GET",
|
||||||
},
|
"http.url": response.effective_url,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
est_value_delta=200,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(client_request_size.name, "http.client.request.size")
|
self.assertEqual(client_request_size.name, "http.client.request.size")
|
||||||
self.assert_metric_expected(
|
self.assert_metric_expected(
|
||||||
client_request_size,
|
client_request_size,
|
||||||
0,
|
self.create_histogram_data_points(
|
||||||
{
|
0,
|
||||||
"http.status_code": response.code,
|
attributes={
|
||||||
"http.method": "GET",
|
"http.status_code": response.code,
|
||||||
"http.url": response.effective_url,
|
"http.method": "GET",
|
||||||
},
|
"http.url": response.effective_url,
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -213,12 +155,14 @@ class TestTornadoInstrumentor(TornadoTest):
|
|||||||
)
|
)
|
||||||
self.assert_metric_expected(
|
self.assert_metric_expected(
|
||||||
client_response_size,
|
client_response_size,
|
||||||
len(response.body),
|
self.create_histogram_data_points(
|
||||||
{
|
len(response.body),
|
||||||
"http.status_code": response.code,
|
attributes={
|
||||||
"http.method": "GET",
|
"http.status_code": response.code,
|
||||||
"http.url": response.effective_url,
|
"http.method": "GET",
|
||||||
},
|
"http.url": response.effective_url,
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_metric_uninstrument(self):
|
def test_metric_uninstrument(self):
|
||||||
@ -226,10 +170,10 @@ class TestTornadoInstrumentor(TornadoTest):
|
|||||||
TornadoInstrumentor().uninstrument()
|
TornadoInstrumentor().uninstrument()
|
||||||
self.fetch("/")
|
self.fetch("/")
|
||||||
|
|
||||||
metrics_list = self.memory_metrics_reader.get_metrics_data()
|
metrics = self.get_sorted_metrics()
|
||||||
for resource_metric in metrics_list.resource_metrics:
|
self.assertEqual(len(metrics), 7)
|
||||||
for scope_metric in resource_metric.scope_metrics:
|
|
||||||
for metric in scope_metric.metrics:
|
for metric in metrics:
|
||||||
for point in list(metric.data.data_points):
|
for point in list(metric.data.data_points):
|
||||||
if isinstance(point, HistogramDataPoint):
|
if isinstance(point, HistogramDataPoint):
|
||||||
self.assertEqual(point.count, 1)
|
self.assertEqual(point.count, 1)
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
|
|
||||||
from timeit import default_timer
|
from timeit import default_timer
|
||||||
from typing import Optional, Union
|
|
||||||
from urllib import request
|
from urllib import request
|
||||||
from urllib.parse import urlencode
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
@ -23,16 +22,11 @@ import httpretty
|
|||||||
from opentelemetry.instrumentation.urllib import ( # pylint: disable=no-name-in-module,import-error
|
from opentelemetry.instrumentation.urllib import ( # pylint: disable=no-name-in-module,import-error
|
||||||
URLLibInstrumentor,
|
URLLibInstrumentor,
|
||||||
)
|
)
|
||||||
from opentelemetry.sdk.metrics._internal.point import Metric
|
|
||||||
from opentelemetry.sdk.metrics.export import (
|
|
||||||
HistogramDataPoint,
|
|
||||||
NumberDataPoint,
|
|
||||||
)
|
|
||||||
from opentelemetry.semconv.metrics import MetricInstruments
|
from opentelemetry.semconv.metrics import MetricInstruments
|
||||||
from opentelemetry.test.test_base import TestBase
|
from opentelemetry.test.test_base import TestBase
|
||||||
|
|
||||||
|
|
||||||
class TestRequestsIntegration(TestBase):
|
class TestUrllibMetricsInstrumentation(TestBase):
|
||||||
URL = "http://httpbin.org/status/200"
|
URL = "http://httpbin.org/status/200"
|
||||||
URL_POST = "http://httpbin.org/post"
|
URL_POST = "http://httpbin.org/post"
|
||||||
|
|
||||||
@ -50,63 +44,13 @@ class TestRequestsIntegration(TestBase):
|
|||||||
URLLibInstrumentor().uninstrument()
|
URLLibInstrumentor().uninstrument()
|
||||||
httpretty.disable()
|
httpretty.disable()
|
||||||
|
|
||||||
def get_sorted_metrics(self):
|
# Return Sequence with one histogram
|
||||||
resource_metrics = (
|
def create_histogram_data_points(self, sum_data_point, attributes):
|
||||||
self.memory_metrics_reader.get_metrics_data().resource_metrics
|
return [
|
||||||
)
|
self.create_histogram_data_point(
|
||||||
|
sum_data_point, 1, sum_data_point, sum_data_point, attributes
|
||||||
all_metrics = []
|
|
||||||
for metrics in resource_metrics:
|
|
||||||
for scope_metrics in metrics.scope_metrics:
|
|
||||||
all_metrics.extend(scope_metrics.metrics)
|
|
||||||
|
|
||||||
return self.sorted_metrics(all_metrics)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def sorted_metrics(metrics):
|
|
||||||
"""
|
|
||||||
Sorts metrics by metric name.
|
|
||||||
"""
|
|
||||||
return sorted(
|
|
||||||
metrics,
|
|
||||||
key=lambda m: m.name,
|
|
||||||
)
|
|
||||||
|
|
||||||
def assert_metric_expected(
|
|
||||||
self,
|
|
||||||
metric: Metric,
|
|
||||||
expected_value: Union[int, float],
|
|
||||||
expected_attributes: dict,
|
|
||||||
est_delta: Optional[float] = None,
|
|
||||||
):
|
|
||||||
data_point = next(iter(metric.data.data_points))
|
|
||||||
|
|
||||||
if isinstance(data_point, HistogramDataPoint):
|
|
||||||
self.assertEqual(
|
|
||||||
data_point.count,
|
|
||||||
1,
|
|
||||||
)
|
)
|
||||||
if est_delta is None:
|
]
|
||||||
self.assertEqual(
|
|
||||||
data_point.sum,
|
|
||||||
expected_value,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
self.assertAlmostEqual(
|
|
||||||
data_point.sum,
|
|
||||||
expected_value,
|
|
||||||
delta=est_delta,
|
|
||||||
)
|
|
||||||
elif isinstance(data_point, NumberDataPoint):
|
|
||||||
self.assertEqual(
|
|
||||||
data_point.value,
|
|
||||||
expected_value,
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertDictEqual(
|
|
||||||
expected_attributes,
|
|
||||||
dict(data_point.attributes),
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_basic_metric(self):
|
def test_basic_metric(self):
|
||||||
start_time = default_timer()
|
start_time = default_timer()
|
||||||
@ -127,31 +71,33 @@ class TestRequestsIntegration(TestBase):
|
|||||||
)
|
)
|
||||||
self.assert_metric_expected(
|
self.assert_metric_expected(
|
||||||
client_duration,
|
client_duration,
|
||||||
client_duration_estimated,
|
self.create_histogram_data_points(
|
||||||
{
|
client_duration_estimated,
|
||||||
"http.status_code": str(result.code),
|
attributes={
|
||||||
"http.method": "GET",
|
"http.status_code": str(result.code),
|
||||||
"http.url": str(result.url),
|
"http.method": "GET",
|
||||||
"http.flavor": "1.1",
|
"http.url": str(result.url),
|
||||||
},
|
"http.flavor": "1.1",
|
||||||
est_delta=200,
|
},
|
||||||
|
),
|
||||||
|
est_value_delta=200,
|
||||||
)
|
)
|
||||||
|
|
||||||
# net.peer.name
|
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
client_request_size.name,
|
client_request_size.name,
|
||||||
MetricInstruments.HTTP_CLIENT_REQUEST_SIZE,
|
MetricInstruments.HTTP_CLIENT_REQUEST_SIZE,
|
||||||
)
|
)
|
||||||
self.assert_metric_expected(
|
self.assert_metric_expected(
|
||||||
client_request_size,
|
client_request_size,
|
||||||
0,
|
self.create_histogram_data_points(
|
||||||
{
|
0,
|
||||||
"http.status_code": str(result.code),
|
attributes={
|
||||||
"http.method": "GET",
|
"http.status_code": str(result.code),
|
||||||
"http.url": str(result.url),
|
"http.method": "GET",
|
||||||
"http.flavor": "1.1",
|
"http.url": str(result.url),
|
||||||
},
|
"http.flavor": "1.1",
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -160,13 +106,15 @@ class TestRequestsIntegration(TestBase):
|
|||||||
)
|
)
|
||||||
self.assert_metric_expected(
|
self.assert_metric_expected(
|
||||||
client_response_size,
|
client_response_size,
|
||||||
result.length,
|
self.create_histogram_data_points(
|
||||||
{
|
result.length,
|
||||||
"http.status_code": str(result.code),
|
attributes={
|
||||||
"http.method": "GET",
|
"http.status_code": str(result.code),
|
||||||
"http.url": str(result.url),
|
"http.method": "GET",
|
||||||
"http.flavor": "1.1",
|
"http.url": str(result.url),
|
||||||
},
|
"http.flavor": "1.1",
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_basic_metric_request_not_empty(self):
|
def test_basic_metric_request_not_empty(self):
|
||||||
@ -191,14 +139,16 @@ class TestRequestsIntegration(TestBase):
|
|||||||
)
|
)
|
||||||
self.assert_metric_expected(
|
self.assert_metric_expected(
|
||||||
client_duration,
|
client_duration,
|
||||||
client_duration_estimated,
|
self.create_histogram_data_points(
|
||||||
{
|
client_duration_estimated,
|
||||||
"http.status_code": str(result.code),
|
attributes={
|
||||||
"http.method": "POST",
|
"http.status_code": str(result.code),
|
||||||
"http.url": str(result.url),
|
"http.method": "POST",
|
||||||
"http.flavor": "1.1",
|
"http.url": str(result.url),
|
||||||
},
|
"http.flavor": "1.1",
|
||||||
est_delta=200,
|
},
|
||||||
|
),
|
||||||
|
est_value_delta=200,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -207,13 +157,15 @@ class TestRequestsIntegration(TestBase):
|
|||||||
)
|
)
|
||||||
self.assert_metric_expected(
|
self.assert_metric_expected(
|
||||||
client_request_size,
|
client_request_size,
|
||||||
len(data_encoded),
|
self.create_histogram_data_points(
|
||||||
{
|
len(data_encoded),
|
||||||
"http.status_code": str(result.code),
|
attributes={
|
||||||
"http.method": "POST",
|
"http.status_code": str(result.code),
|
||||||
"http.url": str(result.url),
|
"http.method": "POST",
|
||||||
"http.flavor": "1.1",
|
"http.url": str(result.url),
|
||||||
},
|
"http.flavor": "1.1",
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -222,13 +174,15 @@ class TestRequestsIntegration(TestBase):
|
|||||||
)
|
)
|
||||||
self.assert_metric_expected(
|
self.assert_metric_expected(
|
||||||
client_response_size,
|
client_response_size,
|
||||||
result.length,
|
self.create_histogram_data_points(
|
||||||
{
|
result.length,
|
||||||
"http.status_code": str(result.code),
|
attributes={
|
||||||
"http.method": "POST",
|
"http.status_code": str(result.code),
|
||||||
"http.url": str(result.url),
|
"http.method": "POST",
|
||||||
"http.flavor": "1.1",
|
"http.url": str(result.url),
|
||||||
},
|
"http.flavor": "1.1",
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_metric_uninstrument(self):
|
def test_metric_uninstrument(self):
|
||||||
|
@ -12,11 +12,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from timeit import default_timer
|
|
||||||
|
|
||||||
import urllib3
|
import urllib3
|
||||||
import urllib3.exceptions
|
import urllib3.exceptions
|
||||||
from urllib3.request import encode_multipart_formdata
|
|
||||||
|
|
||||||
from opentelemetry import trace
|
from opentelemetry import trace
|
||||||
from opentelemetry.instrumentation.urllib3 import URLLib3Instrumentor
|
from opentelemetry.instrumentation.urllib3 import URLLib3Instrumentor
|
||||||
@ -87,136 +84,3 @@ class TestURLLib3InstrumentorWithRealSocket(HttpTestBase, TestBase):
|
|||||||
"net.peer.ip": self.assert_ip,
|
"net.peer.ip": self.assert_ip,
|
||||||
}
|
}
|
||||||
self.assertGreaterEqual(span.attributes.items(), attributes.items())
|
self.assertGreaterEqual(span.attributes.items(), attributes.items())
|
||||||
|
|
||||||
|
|
||||||
class TestURLLib3InstrumentorMetric(HttpTestBase, TestBase):
|
|
||||||
def setUp(self):
|
|
||||||
super().setUp()
|
|
||||||
self.assert_ip = self.server.server_address[0]
|
|
||||||
self.assert_port = self.server.server_address[1]
|
|
||||||
self.http_host = ":".join(map(str, self.server.server_address[:2]))
|
|
||||||
self.http_url_base = "http://" + self.http_host
|
|
||||||
self.http_url = self.http_url_base + "/status/200"
|
|
||||||
URLLib3Instrumentor().instrument(meter_provider=self.meter_provider)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
super().tearDown()
|
|
||||||
URLLib3Instrumentor().uninstrument()
|
|
||||||
|
|
||||||
def test_metric_uninstrument(self):
|
|
||||||
with urllib3.PoolManager() as pool:
|
|
||||||
pool.request("GET", self.http_url)
|
|
||||||
URLLib3Instrumentor().uninstrument()
|
|
||||||
pool.request("GET", self.http_url)
|
|
||||||
|
|
||||||
metrics_list = self.memory_metrics_reader.get_metrics_data()
|
|
||||||
for resource_metric in metrics_list.resource_metrics:
|
|
||||||
for scope_metric in resource_metric.scope_metrics:
|
|
||||||
for metric in scope_metric.metrics:
|
|
||||||
for point in list(metric.data.data_points):
|
|
||||||
self.assertEqual(point.count, 1)
|
|
||||||
|
|
||||||
def test_basic_metric_check_client_size_get(self):
|
|
||||||
with urllib3.PoolManager() as pool:
|
|
||||||
start_time = default_timer()
|
|
||||||
response = pool.request("GET", self.http_url)
|
|
||||||
client_duration_estimated = (default_timer() - start_time) * 1000
|
|
||||||
|
|
||||||
expected_attributes = {
|
|
||||||
"http.status_code": 200,
|
|
||||||
"http.host": self.assert_ip,
|
|
||||||
"http.method": "GET",
|
|
||||||
"http.flavor": "1.1",
|
|
||||||
"http.scheme": "http",
|
|
||||||
"net.peer.name": self.assert_ip,
|
|
||||||
"net.peer.port": self.assert_port,
|
|
||||||
}
|
|
||||||
expected_data = {
|
|
||||||
"http.client.request.size": 0,
|
|
||||||
"http.client.response.size": len(response.data),
|
|
||||||
}
|
|
||||||
expected_metrics = [
|
|
||||||
"http.client.duration",
|
|
||||||
"http.client.request.size",
|
|
||||||
"http.client.response.size",
|
|
||||||
]
|
|
||||||
|
|
||||||
resource_metrics = (
|
|
||||||
self.memory_metrics_reader.get_metrics_data().resource_metrics
|
|
||||||
)
|
|
||||||
for metrics in resource_metrics:
|
|
||||||
for scope_metrics in metrics.scope_metrics:
|
|
||||||
self.assertEqual(len(scope_metrics.metrics), 3)
|
|
||||||
for metric in scope_metrics.metrics:
|
|
||||||
for data_point in metric.data.data_points:
|
|
||||||
if metric.name in expected_data:
|
|
||||||
self.assertEqual(
|
|
||||||
data_point.sum, expected_data[metric.name]
|
|
||||||
)
|
|
||||||
if metric.name == "http.client.duration":
|
|
||||||
self.assertAlmostEqual(
|
|
||||||
data_point.sum,
|
|
||||||
client_duration_estimated,
|
|
||||||
delta=1000,
|
|
||||||
)
|
|
||||||
self.assertIn(metric.name, expected_metrics)
|
|
||||||
self.assertDictEqual(
|
|
||||||
expected_attributes,
|
|
||||||
dict(data_point.attributes),
|
|
||||||
)
|
|
||||||
self.assertEqual(data_point.count, 1)
|
|
||||||
|
|
||||||
def test_basic_metric_check_client_size_post(self):
|
|
||||||
with urllib3.PoolManager() as pool:
|
|
||||||
start_time = default_timer()
|
|
||||||
data_fields = {"data": "test"}
|
|
||||||
response = pool.request("POST", self.http_url, fields=data_fields)
|
|
||||||
client_duration_estimated = (default_timer() - start_time) * 1000
|
|
||||||
|
|
||||||
expected_attributes = {
|
|
||||||
"http.status_code": 501,
|
|
||||||
"http.host": self.assert_ip,
|
|
||||||
"http.method": "POST",
|
|
||||||
"http.flavor": "1.1",
|
|
||||||
"http.scheme": "http",
|
|
||||||
"net.peer.name": self.assert_ip,
|
|
||||||
"net.peer.port": self.assert_port,
|
|
||||||
}
|
|
||||||
|
|
||||||
body = encode_multipart_formdata(data_fields)[0]
|
|
||||||
|
|
||||||
expected_data = {
|
|
||||||
"http.client.request.size": len(body),
|
|
||||||
"http.client.response.size": len(response.data),
|
|
||||||
}
|
|
||||||
expected_metrics = [
|
|
||||||
"http.client.duration",
|
|
||||||
"http.client.request.size",
|
|
||||||
"http.client.response.size",
|
|
||||||
]
|
|
||||||
|
|
||||||
resource_metrics = (
|
|
||||||
self.memory_metrics_reader.get_metrics_data().resource_metrics
|
|
||||||
)
|
|
||||||
for metrics in resource_metrics:
|
|
||||||
for scope_metrics in metrics.scope_metrics:
|
|
||||||
self.assertEqual(len(scope_metrics.metrics), 3)
|
|
||||||
for metric in scope_metrics.metrics:
|
|
||||||
for data_point in metric.data.data_points:
|
|
||||||
if metric.name in expected_data:
|
|
||||||
self.assertEqual(
|
|
||||||
data_point.sum, expected_data[metric.name]
|
|
||||||
)
|
|
||||||
if metric.name == "http.client.duration":
|
|
||||||
self.assertAlmostEqual(
|
|
||||||
data_point.sum,
|
|
||||||
client_duration_estimated,
|
|
||||||
delta=1000,
|
|
||||||
)
|
|
||||||
self.assertIn(metric.name, expected_metrics)
|
|
||||||
|
|
||||||
self.assertDictEqual(
|
|
||||||
expected_attributes,
|
|
||||||
dict(data_point.attributes),
|
|
||||||
)
|
|
||||||
self.assertEqual(data_point.count, 1)
|
|
||||||
|
@ -0,0 +1,203 @@
|
|||||||
|
# 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 timeit import default_timer
|
||||||
|
|
||||||
|
import urllib3
|
||||||
|
import urllib3.exceptions
|
||||||
|
from urllib3.request import encode_multipart_formdata
|
||||||
|
|
||||||
|
from opentelemetry.instrumentation.urllib3 import URLLib3Instrumentor
|
||||||
|
from opentelemetry.test.httptest import HttpTestBase
|
||||||
|
from opentelemetry.test.test_base import TestBase
|
||||||
|
|
||||||
|
|
||||||
|
class TestUrllib3MetricsInstrumentation(HttpTestBase, TestBase):
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
self.assert_ip = self.server.server_address[0]
|
||||||
|
self.assert_port = self.server.server_address[1]
|
||||||
|
self.http_host = ":".join(map(str, self.server.server_address[:2]))
|
||||||
|
self.http_url_base = "http://" + self.http_host
|
||||||
|
self.http_url = self.http_url_base + "/status/200"
|
||||||
|
URLLib3Instrumentor().instrument(meter_provider=self.meter_provider)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super().tearDown()
|
||||||
|
URLLib3Instrumentor().uninstrument()
|
||||||
|
|
||||||
|
# Return Sequence with one histogram
|
||||||
|
def create_histogram_data_points(self, sum_data_point, attributes):
|
||||||
|
return [
|
||||||
|
self.create_histogram_data_point(
|
||||||
|
sum_data_point, 1, sum_data_point, sum_data_point, attributes
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
def test_basic_metric_check_client_size_get(self):
|
||||||
|
with urllib3.PoolManager() as pool:
|
||||||
|
start_time = default_timer()
|
||||||
|
response = pool.request("GET", self.http_url)
|
||||||
|
client_duration_estimated = (default_timer() - start_time) * 1000
|
||||||
|
|
||||||
|
metrics = self.get_sorted_metrics()
|
||||||
|
|
||||||
|
(
|
||||||
|
client_duration,
|
||||||
|
client_request_size,
|
||||||
|
client_response_size,
|
||||||
|
) = metrics
|
||||||
|
|
||||||
|
self.assertEqual(client_duration.name, "http.client.duration")
|
||||||
|
self.assert_metric_expected(
|
||||||
|
client_duration,
|
||||||
|
self.create_histogram_data_points(
|
||||||
|
client_duration_estimated,
|
||||||
|
attributes={
|
||||||
|
"http.status_code": 200,
|
||||||
|
"http.host": self.assert_ip,
|
||||||
|
"http.method": "GET",
|
||||||
|
"http.flavor": "1.1",
|
||||||
|
"http.scheme": "http",
|
||||||
|
"net.peer.name": self.assert_ip,
|
||||||
|
"net.peer.port": self.assert_port,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
est_value_delta=200,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
client_request_size.name, "http.client.request.size"
|
||||||
|
)
|
||||||
|
self.assert_metric_expected(
|
||||||
|
client_request_size,
|
||||||
|
self.create_histogram_data_points(
|
||||||
|
0,
|
||||||
|
attributes={
|
||||||
|
"http.status_code": 200,
|
||||||
|
"http.host": self.assert_ip,
|
||||||
|
"http.method": "GET",
|
||||||
|
"http.flavor": "1.1",
|
||||||
|
"http.scheme": "http",
|
||||||
|
"net.peer.name": self.assert_ip,
|
||||||
|
"net.peer.port": self.assert_port,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
client_response_size.name, "http.client.response.size"
|
||||||
|
)
|
||||||
|
self.assert_metric_expected(
|
||||||
|
client_response_size,
|
||||||
|
self.create_histogram_data_points(
|
||||||
|
len(response.data),
|
||||||
|
attributes={
|
||||||
|
"http.status_code": 200,
|
||||||
|
"http.host": self.assert_ip,
|
||||||
|
"http.method": "GET",
|
||||||
|
"http.flavor": "1.1",
|
||||||
|
"http.scheme": "http",
|
||||||
|
"net.peer.name": self.assert_ip,
|
||||||
|
"net.peer.port": self.assert_port,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_basic_metric_check_client_size_post(self):
|
||||||
|
with urllib3.PoolManager() as pool:
|
||||||
|
start_time = default_timer()
|
||||||
|
data_fields = {"data": "test"}
|
||||||
|
response = pool.request("POST", self.http_url, fields=data_fields)
|
||||||
|
client_duration_estimated = (default_timer() - start_time) * 1000
|
||||||
|
body = encode_multipart_formdata(data_fields)[0]
|
||||||
|
|
||||||
|
metrics = self.get_sorted_metrics()
|
||||||
|
|
||||||
|
(
|
||||||
|
client_duration,
|
||||||
|
client_request_size,
|
||||||
|
client_response_size,
|
||||||
|
) = metrics
|
||||||
|
|
||||||
|
self.assertEqual(client_duration.name, "http.client.duration")
|
||||||
|
self.assert_metric_expected(
|
||||||
|
client_duration,
|
||||||
|
self.create_histogram_data_points(
|
||||||
|
client_duration_estimated,
|
||||||
|
attributes={
|
||||||
|
"http.status_code": 501,
|
||||||
|
"http.host": self.assert_ip,
|
||||||
|
"http.method": "POST",
|
||||||
|
"http.flavor": "1.1",
|
||||||
|
"http.scheme": "http",
|
||||||
|
"net.peer.name": self.assert_ip,
|
||||||
|
"net.peer.port": self.assert_port,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
est_value_delta=200,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
client_request_size.name, "http.client.request.size"
|
||||||
|
)
|
||||||
|
client_request_size_expected = len(body)
|
||||||
|
self.assert_metric_expected(
|
||||||
|
client_request_size,
|
||||||
|
self.create_histogram_data_points(
|
||||||
|
client_request_size_expected,
|
||||||
|
attributes={
|
||||||
|
"http.status_code": 501,
|
||||||
|
"http.host": self.assert_ip,
|
||||||
|
"http.method": "POST",
|
||||||
|
"http.flavor": "1.1",
|
||||||
|
"http.scheme": "http",
|
||||||
|
"net.peer.name": self.assert_ip,
|
||||||
|
"net.peer.port": self.assert_port,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
client_response_size.name, "http.client.response.size"
|
||||||
|
)
|
||||||
|
client_response_size_expected = len(response.data)
|
||||||
|
self.assert_metric_expected(
|
||||||
|
client_response_size,
|
||||||
|
self.create_histogram_data_points(
|
||||||
|
client_response_size_expected,
|
||||||
|
attributes={
|
||||||
|
"http.status_code": 501,
|
||||||
|
"http.host": self.assert_ip,
|
||||||
|
"http.method": "POST",
|
||||||
|
"http.flavor": "1.1",
|
||||||
|
"http.scheme": "http",
|
||||||
|
"net.peer.name": self.assert_ip,
|
||||||
|
"net.peer.port": self.assert_port,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_metric_uninstrument(self):
|
||||||
|
with urllib3.PoolManager() as pool:
|
||||||
|
pool.request("GET", self.http_url)
|
||||||
|
URLLib3Instrumentor().uninstrument()
|
||||||
|
pool.request("GET", self.http_url)
|
||||||
|
|
||||||
|
metrics = self.get_sorted_metrics()
|
||||||
|
self.assertEqual(len(metrics), 3)
|
||||||
|
|
||||||
|
for metric in metrics:
|
||||||
|
for point in list(metric.data.data_points):
|
||||||
|
self.assertEqual(point.count, 1)
|
Reference in New Issue
Block a user