From 2e44fb7e56750a856d6309561ebb0bb7e28604db Mon Sep 17 00:00:00 2001 From: Alexander Wert Date: Wed, 27 Sep 2023 08:11:51 +0200 Subject: [PATCH 1/2] Fix referring template attributes Signed-off-by: Alexander Wert --- .../semconv/model/semantic_convention.py | 20 +++---- .../attribute_templates.yaml | 22 ++++++++ .../markdown/attribute_templates/expected.md | 4 +- .../markdown/attribute_templates/input.md | 2 +- .../tests/semconv/model/test_correct_parse.py | 52 ++++++++++--------- 5 files changed, 65 insertions(+), 35 deletions(-) diff --git a/semantic-conventions/src/opentelemetry/semconv/model/semantic_convention.py b/semantic-conventions/src/opentelemetry/semconv/model/semantic_convention.py index 6f91ae2e..3d952e1e 100644 --- a/semantic-conventions/src/opentelemetry/semconv/model/semantic_convention.py +++ b/semantic-conventions/src/opentelemetry/semconv/model/semantic_convention.py @@ -153,7 +153,7 @@ def __init__(self, group): ) def contains_attribute(self, attr: "SemanticAttribute"): - for local_attr in self.attributes: + for local_attr in self.attributes_and_templates: if local_attr.attr_id is not None: if local_attr.fqn == attr.fqn: return True @@ -162,24 +162,26 @@ def contains_attribute(self, attr: "SemanticAttribute"): return False def all_attributes(self): - return unique_attributes(self.attributes + self.conditional_attributes()) + return unique_attributes( + self.attributes_and_templates + self.conditional_attributes() + ) def sampling_attributes(self): return unique_attributes( - attr for attr in self.attributes if attr.sampling_relevant + attr for attr in self.attributes_and_templates if attr.sampling_relevant ) def required_attributes(self): return unique_attributes( attr - for attr in self.attributes + for attr in self.attributes_and_templates if attr.requirement_level == RequirementLevel.REQUIRED ) def conditional_attributes(self): return unique_attributes( attr - for attr in self.attributes + for attr in self.attributes_and_templates if attr.requirement_level == RequirementLevel.CONDITIONALLY_REQUIRED ) @@ -343,7 +345,7 @@ def has_error(self): def check_unique_fqns(self): group_by_fqn: typing.Dict[str, str] = {} for model in self.models.values(): - for attr in model.attributes: + for attr in model.attributes_and_templates: if not attr.ref: if attr.fqn in group_by_fqn: self.errors = True @@ -429,7 +431,7 @@ def _populate_extends_single(self, semconv, unprocessed): semconv.constraints += (constraint.inherit_anyof(),) # Attributes parent_attributes = {} - for ext_attr in extended.attributes: + for ext_attr in extended.attributes_and_templates: parent_attributes[ext_attr.fqn] = ext_attr.inherit_attribute() # By induction, parent semconv is already correctly sorted parent_attributes.update( @@ -556,7 +558,7 @@ def resolve_include(self, semconv): include_semconv, {include_semconv.semconv_id: include_semconv} ) attr: SemanticAttribute - for attr in include_semconv.attributes: + for attr in include_semconv.attributes_and_templates: if semconv.contains_attribute(attr): if self.debug: print( @@ -585,7 +587,7 @@ def _lookup_attribute(self, attr_id: str) -> Union[SemanticAttribute, None]: ( attr for model in self.models.values() - for attr in model.attributes + for attr in model.attributes_and_templates if attr.fqn == attr_id and attr.ref is None ), None, diff --git a/semantic-conventions/src/tests/data/markdown/attribute_templates/attribute_templates.yaml b/semantic-conventions/src/tests/data/markdown/attribute_templates/attribute_templates.yaml index aad943a6..ebaa1644 100644 --- a/semantic-conventions/src/tests/data/markdown/attribute_templates/attribute_templates.yaml +++ b/semantic-conventions/src/tests/data/markdown/attribute_templates/attribute_templates.yaml @@ -6,6 +6,7 @@ groups: note: > These conventions can be used for http and https schemes and various HTTP versions like 1.1, 2 and SPDY. + extends: general attributes: - id: request.header type: template[string[]] @@ -19,3 +20,24 @@ groups: sampling_relevant: false brief: 'HTTP request method.' examples: ["GET", "POST", "HEAD"] + - ref: referenced_http.request.referenced.header + - id: referenced_http_id + type: span + prefix: referenced_http + brief: 'This document defines semantic conventions for HTTP client and server Spans.' + attributes: + - id: request.referenced.header + type: template[string[]] + brief: > + This is a referenced attribute. + examples: '`http.request.header.content_type=["application/json"]`' + - id: general + type: span + prefix: general + brief: 'This document defines general attributes.' + attributes: + - id: some_general_attribute + type: template[string] + brief: > + This is a general attribute. + examples: '`some_general_attribute.some_key="abc"`' diff --git a/semantic-conventions/src/tests/data/markdown/attribute_templates/expected.md b/semantic-conventions/src/tests/data/markdown/attribute_templates/expected.md index 24499613..5cd2a5be 100644 --- a/semantic-conventions/src/tests/data/markdown/attribute_templates/expected.md +++ b/semantic-conventions/src/tests/data/markdown/attribute_templates/expected.md @@ -1,8 +1,10 @@ # Custom HTTP Semantic Conventions - + | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| +| `general.some_general_attribute.` | string | This is a general attribute. | ``some_general_attribute.some_key="abc"`` | Recommended | | `custom_http.request.header.` | string[] | HTTP request headers, `` being the normalized HTTP Header name (lowercase, with - characters replaced by _), the value being the header values. | ``http.request.header.content_type=["application/json"]`` | Recommended | | `custom_http.request.method` | string | HTTP request method. | `GET`; `POST`; `HEAD` | Required | +| `referenced_http.request.referenced.header.` | string[] | This is a referenced attribute. | ``http.request.header.content_type=["application/json"]`` | Recommended | diff --git a/semantic-conventions/src/tests/data/markdown/attribute_templates/input.md b/semantic-conventions/src/tests/data/markdown/attribute_templates/input.md index 9d5e48a8..d6fc6a88 100644 --- a/semantic-conventions/src/tests/data/markdown/attribute_templates/input.md +++ b/semantic-conventions/src/tests/data/markdown/attribute_templates/input.md @@ -1,4 +1,4 @@ # Custom HTTP Semantic Conventions - + diff --git a/semantic-conventions/src/tests/semconv/model/test_correct_parse.py b/semantic-conventions/src/tests/semconv/model/test_correct_parse.py index eafaaa94..f6f8810c 100644 --- a/semantic-conventions/src/tests/semconv/model/test_correct_parse.py +++ b/semantic-conventions/src/tests/semconv/model/test_correct_parse.py @@ -334,7 +334,7 @@ def test_markdown_link(self): semconv.finish() self.assertEqual(len(semconv.models), 1) s = list(semconv.models.values())[0] - for attr in s.attributes: + for attr in s.attributes_and_templates: brief = attr.brief self.assertEqual(brief.raw_text, str(brief)) @@ -348,11 +348,11 @@ def test_ref(self): client = list(semconv.models.values())[1] server = list(semconv.models.values())[2] - self.assertIsNotNone(client.attributes[1].ref) - self.assertIsNotNone(client.attributes[1].attr_type) + self.assertIsNotNone(client.attributes_and_templates[1].ref) + self.assertIsNotNone(client.attributes_and_templates[1].attr_type) - self.assertIsNotNone(server.attributes[1].ref) - self.assertIsNotNone(server.attributes[1].attr_type) + self.assertIsNotNone(server.attributes_and_templates[1].ref) + self.assertIsNotNone(server.attributes_and_templates[1].attr_type) def test_extends(self): semconv = SemanticConventionSet(debug=False) @@ -458,12 +458,16 @@ def test_deprecation(self): semconv.finish() self.assertEqual(len(semconv.models), 1) - self.assertIsNotNone(list(semconv.models.values())[0].attributes[0].deprecated) + self.assertIsNotNone( + list(semconv.models.values())[0].attributes_and_templates[0].deprecated + ) self.assertEqual( - list(semconv.models.values())[0].attributes[0].deprecated, + list(semconv.models.values())[0].attributes_and_templates[0].deprecated, "Use attribute `nonDepecrated`.", ) - self.assertIsNone(list(semconv.models.values())[0].attributes[3].deprecated) + self.assertIsNone( + list(semconv.models.values())[0].attributes_and_templates[3].deprecated + ) def test_stability(self): semconv = SemanticConventionSet(debug=False) @@ -472,42 +476,42 @@ def test_stability(self): self.assertEqual(len(semconv.models), 6) model = list(semconv.models.values())[0] - self.assertEqual(len(model.attributes), 4) + self.assertEqual(len(model.attributes_and_templates), 4) self.assertEqual(model.stability, None) - attr = model.attributes[0] + attr = model.attributes_and_templates[0] self.assertEqual(attr.attr_id, "exp_attr") self.assertEqual(attr.stability, StabilityLevel.EXPERIMENTAL) - attr = model.attributes[1] + attr = model.attributes_and_templates[1] self.assertEqual(attr.attr_id, "stable_attr") self.assertEqual(attr.stability, StabilityLevel.STABLE) - attr = model.attributes[2] + attr = model.attributes_and_templates[2] self.assertEqual(attr.attr_id, "deprecated_attr") self.assertEqual(attr.stability, StabilityLevel.DEPRECATED) - attr = model.attributes[3] + attr = model.attributes_and_templates[3] self.assertEqual(attr.attr_id, "def_stability") self.assertEqual(attr.stability, StabilityLevel.EXPERIMENTAL) model = list(semconv.models.values())[1] - self.assertEqual(len(model.attributes), 2) + self.assertEqual(len(model.attributes_and_templates), 2) self.assertEqual(model.stability, StabilityLevel.EXPERIMENTAL) - attr = model.attributes[0] + attr = model.attributes_and_templates[0] self.assertEqual(attr.attr_id, "test_attr") self.assertEqual(attr.stability, StabilityLevel.EXPERIMENTAL) - attr = model.attributes[1] + attr = model.attributes_and_templates[1] self.assertEqual(attr.attr_id, "dep") self.assertEqual(attr.stability, StabilityLevel.DEPRECATED) model = list(semconv.models.values())[2] - self.assertEqual(len(model.attributes), 1) + self.assertEqual(len(model.attributes_and_templates), 1) self.assertEqual(model.stability, StabilityLevel.DEPRECATED) - attr = model.attributes[0] + attr = model.attributes_and_templates[0] self.assertEqual(attr.attr_id, "test_attr") self.assertEqual(attr.stability, StabilityLevel.DEPRECATED) @@ -546,7 +550,7 @@ def test_inherited_imported(self): models = sorted(semconv.models.values(), key=lambda m: m.semconv_id) self.assertEqual(len(models), 6) # HTTP - attrs = models[0].attributes + attrs = models[0].attributes_and_templates self.assertEqual(models[0].semconv_id, "http") self.assertEqual(len(attrs), 2) @@ -561,7 +565,7 @@ def test_inherited_imported(self): self.assertEqual(attrs[1].ref, "net.peer.port") # Network - attrs = models[1].attributes + attrs = models[1].attributes_and_templates self.assertEqual(models[1].semconv_id, "network") self.assertEqual(len(attrs), 3) @@ -582,7 +586,7 @@ def test_inherited_imported(self): self.assertEqual(attrs[2].ref, None) # Base - rpc - attrs = models[2].attributes + attrs = models[2].attributes_and_templates self.assertEqual(models[2].semconv_id, "rpc") self.assertEqual(len(attrs), 4) # Included attributes @@ -608,7 +612,7 @@ def test_inherited_imported(self): self.assertEqual(attrs[3].ref, None) # Extended - rpc.client - attrs = models[3].attributes + attrs = models[3].attributes_and_templates self.assertEqual(models[3].semconv_id, "rpc.client") self.assertEqual(len(attrs), 6) # Parent attributes @@ -645,7 +649,7 @@ def test_inherited_imported(self): self.assertEqual(attrs[5].ref, None) # Include on Extended - zother - attrs = models[4].attributes + attrs = models[4].attributes_and_templates self.assertEqual(models[4].semconv_id, "zother") self.assertEqual(len(attrs), 1) # Defined attributes @@ -655,7 +659,7 @@ def test_inherited_imported(self): self.assertEqual(attrs[0].ref, None) # Include on Extended - zz.rpc.client - attrs = models[5].attributes + attrs = models[5].attributes_and_templates self.assertEqual(models[5].semconv_id, "zz.rpc.client") self.assertEqual(len(attrs), 8) # Parent attributes From c9ba374676e3520d85ba904b5da125f28d974b95 Mon Sep 17 00:00:00 2001 From: Alexander Wert Date: Thu, 28 Sep 2023 16:32:46 +0200 Subject: [PATCH 2/2] fix template test expected ordering Signed-off-by: Alexander Wert --- .../src/tests/data/markdown/attribute_templates/expected.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/semantic-conventions/src/tests/data/markdown/attribute_templates/expected.md b/semantic-conventions/src/tests/data/markdown/attribute_templates/expected.md index 5cd2a5be..f304d72a 100644 --- a/semantic-conventions/src/tests/data/markdown/attribute_templates/expected.md +++ b/semantic-conventions/src/tests/data/markdown/attribute_templates/expected.md @@ -3,8 +3,8 @@ | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| -| `general.some_general_attribute.` | string | This is a general attribute. | ``some_general_attribute.some_key="abc"`` | Recommended | | `custom_http.request.header.` | string[] | HTTP request headers, `` being the normalized HTTP Header name (lowercase, with - characters replaced by _), the value being the header values. | ``http.request.header.content_type=["application/json"]`` | Recommended | | `custom_http.request.method` | string | HTTP request method. | `GET`; `POST`; `HEAD` | Required | +| `general.some_general_attribute.` | string | This is a general attribute. | ``some_general_attribute.some_key="abc"`` | Recommended | | `referenced_http.request.referenced.header.` | string[] | This is a referenced attribute. | ``http.request.header.content_type=["application/json"]`` | Recommended |