Skip to content

Commit d2772ea

Browse files
Add tests
1 parent c897bdb commit d2772ea

File tree

2 files changed

+213
-0
lines changed

2 files changed

+213
-0
lines changed

instrumentation/opentelemetry-instrumentation-pyramid/tests/test_automatic.py

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,26 @@
1919

2020
from opentelemetry import trace
2121
from opentelemetry.instrumentation._semconv import (
22+
OTEL_SEMCONV_STABILITY_OPT_IN,
23+
_OpenTelemetrySemanticConventionStability,
2224
_server_active_requests_count_attrs_old,
2325
_server_duration_attrs_old,
26+
_StabilityMode,
2427
)
2528
from opentelemetry.instrumentation.pyramid import PyramidInstrumentor
2629
from opentelemetry.sdk.metrics.export import (
2730
HistogramDataPoint,
2831
NumberDataPoint,
2932
)
33+
from opentelemetry.semconv._incubating.attributes.http_attributes import (
34+
HTTP_ROUTE,
35+
)
36+
from opentelemetry.semconv.attributes.server_attributes import (
37+
SERVER_ADDRESS,
38+
SERVER_PORT,
39+
)
40+
from opentelemetry.semconv.attributes.url_attributes import URL_SCHEME
41+
from opentelemetry.semconv.trace import SpanAttributes
3042
from opentelemetry.test.globals_test import reset_trace_globals
3143
from opentelemetry.test.wsgitestutil import WsgiTestBase
3244
from opentelemetry.trace import SpanKind
@@ -409,6 +421,201 @@ def test_custom_response_header_not_added_in_internal_span(self):
409421
self.assertNotIn(key, span.attributes)
410422

411423

424+
class _SemConvTestBase(InstrumentationTest, WsgiTestBase):
425+
semconv_mode = _StabilityMode.DEFAULT
426+
427+
def setUp(self):
428+
super().setUp()
429+
self.env_patch = patch.dict(
430+
"os.environ",
431+
{OTEL_SEMCONV_STABILITY_OPT_IN: self.semconv_mode.value},
432+
)
433+
_OpenTelemetrySemanticConventionStability._initialized = False
434+
self.env_patch.start()
435+
436+
PyramidInstrumentor().instrument()
437+
self.config = Configurator()
438+
self._common_initialization(self.config)
439+
440+
def tearDown(self):
441+
super().tearDown()
442+
self.env_patch.stop()
443+
with self.disable_logging():
444+
PyramidInstrumentor().uninstrument()
445+
446+
def _verify_metric_names(
447+
self, metrics_list, expected_names, not_expected_names=None
448+
):
449+
metric_names = []
450+
for resource_metric in metrics_list.resource_metrics:
451+
for scope_metric in resource_metric.scope_metrics:
452+
for metric in scope_metric.metrics:
453+
metric_names.append(metric.name)
454+
if expected_names:
455+
self.assertIn(metric.name, expected_names)
456+
if not_expected_names:
457+
self.assertNotIn(metric.name, not_expected_names)
458+
return metric_names
459+
460+
def _verify_duration_point(self, point):
461+
self.assertIn("http.request.method", point.attributes)
462+
self.assertIn("url.scheme", point.attributes)
463+
self.assertNotIn("http.method", point.attributes)
464+
self.assertNotIn("http.scheme", point.attributes)
465+
466+
def _verify_metric_duration(self, metric):
467+
if "duration" in metric.name:
468+
for point in metric.data.data_points:
469+
if isinstance(point, HistogramDataPoint):
470+
self._verify_duration_point(point)
471+
472+
def _verify_duration_attributes(self, metrics_list):
473+
for resource_metric in metrics_list.resource_metrics:
474+
for scope_metric in resource_metric.scope_metrics:
475+
for metric in scope_metric.metrics:
476+
self._verify_metric_duration(metric)
477+
478+
479+
class TestSemConvDefault(_SemConvTestBase):
480+
semconv_mode = _StabilityMode.DEFAULT
481+
482+
def test_basic_old_semconv(self):
483+
resp = self.client.get("/hello/123")
484+
self.assertEqual(200, resp.status_code)
485+
486+
span = self.memory_exporter.get_finished_spans()[0]
487+
488+
old_attrs = {
489+
SpanAttributes.HTTP_METHOD: "GET",
490+
SpanAttributes.HTTP_SCHEME: "http",
491+
SpanAttributes.HTTP_HOST: "localhost",
492+
SpanAttributes.HTTP_TARGET: "/hello/123",
493+
SpanAttributes.NET_HOST_PORT: 80,
494+
SpanAttributes.HTTP_STATUS_CODE: 200,
495+
SpanAttributes.HTTP_FLAVOR: "1.1",
496+
HTTP_ROUTE: "/hello/{helloid}",
497+
}
498+
for attr, value in old_attrs.items():
499+
self.assertEqual(span.attributes[attr], value)
500+
501+
for attr in [SERVER_ADDRESS, SERVER_PORT, URL_SCHEME]:
502+
self.assertNotIn(attr, span.attributes)
503+
504+
def test_metrics_old_semconv(self):
505+
self.client.get("/hello/123")
506+
507+
metrics_list = self.memory_metrics_reader.get_metrics_data()
508+
self.assertTrue(len(metrics_list.resource_metrics) == 1)
509+
510+
expected_metrics = [
511+
"http.server.active_requests",
512+
"http.server.duration",
513+
]
514+
self._verify_metric_names(
515+
metrics_list, expected_metrics, ["http.server.request.duration"]
516+
)
517+
518+
for resource_metric in metrics_list.resource_metrics:
519+
for scope_metric in resource_metric.scope_metrics:
520+
for metric in scope_metric.metrics:
521+
for point in metric.data.data_points:
522+
if isinstance(point, HistogramDataPoint):
523+
self.assertIn("http.method", point.attributes)
524+
self.assertIn("http.scheme", point.attributes)
525+
self.assertNotIn(
526+
"http.request.method", point.attributes
527+
)
528+
529+
530+
class TestSemConvNew(_SemConvTestBase):
531+
semconv_mode = _StabilityMode.HTTP
532+
533+
def test_basic_new_semconv(self):
534+
resp = self.client.get("/hello/456")
535+
self.assertEqual(200, resp.status_code)
536+
537+
span = self.memory_exporter.get_finished_spans()[0]
538+
539+
new_attrs = {
540+
"http.request.method": "GET",
541+
URL_SCHEME: "http",
542+
SERVER_ADDRESS: "localhost",
543+
SERVER_PORT: 80,
544+
"http.response.status_code": 200,
545+
"network.protocol.version": "1.1",
546+
HTTP_ROUTE: "/hello/{helloid}",
547+
}
548+
for attr, value in new_attrs.items():
549+
self.assertEqual(span.attributes[attr], value)
550+
551+
old_attrs = [
552+
SpanAttributes.HTTP_METHOD,
553+
SpanAttributes.HTTP_HOST,
554+
SpanAttributes.HTTP_TARGET,
555+
SpanAttributes.HTTP_URL,
556+
]
557+
for attr in old_attrs:
558+
self.assertNotIn(attr, span.attributes)
559+
560+
def test_metrics_new_semconv(self):
561+
self.client.get("/hello/456")
562+
metrics_list = self.memory_metrics_reader.get_metrics_data()
563+
self.assertTrue(len(metrics_list.resource_metrics) == 1)
564+
565+
expected_metrics = [
566+
"http.server.request.duration",
567+
"http.server.active_requests",
568+
]
569+
metric_names = self._verify_metric_names(
570+
metrics_list, expected_metrics
571+
)
572+
573+
self.assertIn("http.server.request.duration", metric_names)
574+
self.assertIn("http.server.active_requests", metric_names)
575+
576+
self._verify_duration_attributes(metrics_list)
577+
578+
579+
class TestSemConvDup(_SemConvTestBase):
580+
semconv_mode = _StabilityMode.HTTP_DUP
581+
582+
def test_basic_both_semconv(self):
583+
resp = self.client.get("/hello/789")
584+
self.assertEqual(200, resp.status_code)
585+
586+
span = self.memory_exporter.get_finished_spans()[0]
587+
588+
expected_attrs = {
589+
SpanAttributes.HTTP_METHOD: "GET",
590+
SpanAttributes.HTTP_SCHEME: "http",
591+
SpanAttributes.HTTP_HOST: "localhost",
592+
SpanAttributes.HTTP_STATUS_CODE: 200,
593+
"http.request.method": "GET",
594+
URL_SCHEME: "http",
595+
SERVER_ADDRESS: "localhost",
596+
"http.response.status_code": 200,
597+
HTTP_ROUTE: "/hello/{helloid}",
598+
}
599+
for attr, value in expected_attrs.items():
600+
self.assertEqual(span.attributes[attr], value)
601+
602+
def test_metrics_both_semconv(self):
603+
self.client.get("/hello/789")
604+
605+
metrics_list = self.memory_metrics_reader.get_metrics_data()
606+
self.assertTrue(len(metrics_list.resource_metrics) == 1)
607+
608+
expected_metrics = [
609+
"http.server.duration",
610+
"http.server.request.duration",
611+
"http.server.active_requests",
612+
]
613+
metric_names = self._verify_metric_names(metrics_list, None)
614+
615+
for metric_name in expected_metrics:
616+
self.assertIn(metric_name, metric_names)
617+
618+
412619
@patch.dict(
413620
"os.environ",
414621
{

instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
from pyramid.config import Configurator
1818

1919
from opentelemetry import trace
20+
from opentelemetry.instrumentation._semconv import (
21+
_OpenTelemetrySemanticConventionStability,
22+
)
2023
from opentelemetry.instrumentation.propagators import (
2124
TraceResponsePropagator,
2225
get_global_response_propagator,
@@ -52,6 +55,9 @@ def expected_attributes(override_attributes):
5255
class TestProgrammatic(InstrumentationTest, WsgiTestBase):
5356
def setUp(self):
5457
super().setUp()
58+
# Reset semconv stability to ensure clean state
59+
_OpenTelemetrySemanticConventionStability._initialized = False
60+
5561
config = Configurator()
5662
PyramidInstrumentor().instrument_config(config)
5763

0 commit comments

Comments
 (0)