From 5252e33eb635fb2503969af935e15578f5f54781 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Wed, 6 Dec 2023 20:35:57 -0800 Subject: [PATCH 1/4] Make stability and deprecation independent properties --- semantic-conventions/CHANGELOG.md | 5 +- .../semconv/model/semantic_attribute.py | 74 +++++++------------ .../semconv/model/semantic_convention.py | 11 +-- .../opentelemetry/semconv/templating/code.py | 12 ++- .../semconv/templating/markdown/__init__.py | 10 +-- .../semconv/templating/markdown/options.py | 30 ++++---- .../data/jinja/attribute_templates/template | 8 +- .../markdown/stability/badges_expected.md | 2 +- .../markdown/stability/labels_expected.md | 2 +- .../data/markdown/stability/stability.yaml | 3 +- .../stability/stability_deprecated.yaml | 13 ---- .../yaml/errors/stability/wrong_value.yaml | 1 - .../src/tests/data/yaml/stability.yaml | 31 ++++---- .../tests/semconv/model/test_correct_parse.py | 23 +++--- .../semconv/model/test_error_detection.py | 15 +--- .../semconv/model/test_semantic_attribute.py | 6 +- semantic-conventions/syntax.md | 41 +++++----- 17 files changed, 120 insertions(+), 167 deletions(-) delete mode 100644 semantic-conventions/src/tests/data/yaml/errors/stability/stability_deprecated.yaml diff --git a/semantic-conventions/CHANGELOG.md b/semantic-conventions/CHANGELOG.md index 153d7587..3ee1a580 100644 --- a/semantic-conventions/CHANGELOG.md +++ b/semantic-conventions/CHANGELOG.md @@ -4,6 +4,9 @@ Please update the changelog as part of any significant pull request. ## Unreleased +- BREAKING: Make stability and deprecation independent attribute and semantic convention properties. + ([#](https://github.com/open-telemetry/build-tools/pull/TODO)) + ## v0.23.0 - Rephrase and relax sampling-relevant description @@ -17,7 +20,7 @@ Please update the changelog as part of any significant pull request. ([#205](https://github.com/open-telemetry/build-tools/pull/205)) - Fix referencing template attributes ([#206](https://github.com/open-telemetry/build-tools/pull/206)) - + ## v0.21.0 - Render template-type attributes from yaml files diff --git a/semantic-conventions/src/opentelemetry/semconv/model/semantic_attribute.py b/semantic-conventions/src/opentelemetry/semconv/model/semantic_attribute.py index f6df923d..e27f654a 100644 --- a/semantic-conventions/src/opentelemetry/semconv/model/semantic_attribute.py +++ b/semantic-conventions/src/opentelemetry/semconv/model/semantic_attribute.py @@ -41,7 +41,6 @@ class RequirementLevel(Enum): class StabilityLevel(Enum): STABLE = 1 EXPERIMENTAL = 2 - DEPRECATED = 3 @dataclass @@ -82,9 +81,7 @@ def is_enum(self): return isinstance(self.attr_type, EnumAttributeType) @staticmethod - def parse( - prefix, semconv_stability, yaml_attributes - ) -> "Dict[str, SemanticAttribute]": + def parse(prefix, yaml_attributes) -> "Dict[str, SemanticAttribute]": """This method parses the yaml representation for semantic attributes creating the respective SemanticAttribute objects. """ @@ -179,21 +176,13 @@ def parse( raise ValidationError.from_yaml_pos(position, msg) tag = attribute.get("tag", "").strip() - stability, deprecated = SemanticAttribute.parse_stability_deprecated( - attribute.get("stability"), attribute.get("deprecated"), position_data + stability = SemanticAttribute.parse_stability( + attribute.get("stability"), position_data ) - if ( - semconv_stability == StabilityLevel.DEPRECATED - and stability is not StabilityLevel.DEPRECATED - ): - position = ( - position_data["stability"] - if "stability" in position_data - else position_data["deprecated"] - ) - msg = f"Semantic convention stability set to deprecated but attribute '{attr_id}' is {stability}" - raise ValidationError.from_yaml_pos(position, msg) - stability = stability or semconv_stability or StabilityLevel.EXPERIMENTAL + deprecated = SemanticAttribute.parse_deprecated( + attribute.get("deprecated"), position_data + ) + sampling_relevant = ( AttributeType.to_bool("sampling_relevant", attribute) if attribute.get("sampling_relevant") @@ -291,44 +280,31 @@ def parse_attribute(attribute): return attr_type, str(brief), examples @staticmethod - def parse_stability_deprecated(stability, deprecated, position_data): - if deprecated is not None and stability is None: - stability = "deprecated" - if deprecated is not None: - if stability is not None and stability != "deprecated": - position = position_data["deprecated"] - msg = f"There is a deprecation message but the stability is set to '{stability}'" - raise ValidationError.from_yaml_pos(position, msg) - if AttributeType.get_type(deprecated) != "string" or deprecated == "": - position = position_data["deprecated"] - msg = ( - "Deprecated field expects a string that specifies why the attribute is deprecated and/or what" - " to use instead! " - ) - raise ValidationError.from_yaml_pos(position, msg) - deprecated = deprecated.strip() - if stability is not None: - stability = SemanticAttribute.check_stability( - stability, - position_data["stability"] - if "stability" in position_data - else position_data["deprecated"], - ) - return stability, deprecated - - @staticmethod - def check_stability(stability_value, position): + def parse_stability(stability, position_data): + if stability is None: + return StabilityLevel.EXPERIMENTAL stability_value_map = { - "deprecated": StabilityLevel.DEPRECATED, "experimental": StabilityLevel.EXPERIMENTAL, "stable": StabilityLevel.STABLE, } - val = stability_value_map.get(stability_value) + val = stability_value_map.get(stability) if val is not None: return val - msg = f"Value '{stability_value}' is not allowed as a stability marker" - raise ValidationError.from_yaml_pos(position, msg) + msg = f"Value '{stability}' is not allowed as a stability marker" + raise ValidationError.from_yaml_pos(position_data["stability"], msg) + + @staticmethod + def parse_deprecated(deprecated, position_data): + if deprecated is not None: + if AttributeType.get_type(deprecated) != "string" or deprecated == "": + msg = ( + "Deprecated field expects a string that specifies why the attribute is deprecated and/or what" + " to use instead! " + ) + raise ValidationError.from_yaml_pos(position_data["deprecated"], msg) + return deprecated.strip() + return None def equivalent_to(self, other: "SemanticAttribute"): if self.attr_id is not None: diff --git a/semantic-conventions/src/opentelemetry/semconv/model/semantic_convention.py b/semantic-conventions/src/opentelemetry/semconv/model/semantic_convention.py index 13ade651..fa6977a9 100644 --- a/semantic-conventions/src/opentelemetry/semconv/model/semantic_convention.py +++ b/semantic-conventions/src/opentelemetry/semconv/model/semantic_convention.py @@ -140,17 +140,18 @@ def __init__(self, group): self.semconv_id = self.id self.note = group.get("note", "").strip() self.prefix = group.get("prefix", "").strip() - stability = group.get("stability") - deprecated = group.get("deprecated") position_data = group.lc.data - self.stability, self.deprecated = SemanticAttribute.parse_stability_deprecated( - stability, deprecated, position_data + self.stability = SemanticAttribute.parse_stability( + group.get("stability"), position_data + ) + self.deprecated = SemanticAttribute.parse_deprecated( + group.get("deprecated"), position_data ) self.extends = group.get("extends", "").strip() self.events = group.get("events", ()) self.constraints = parse_constraints(group.get("constraints", ())) self.attrs_by_name = SemanticAttribute.parse( - self.prefix, self.stability, group.get("attributes") + self.prefix, group.get("attributes") ) def contains_attribute(self, attr: "SemanticAttribute"): diff --git a/semantic-conventions/src/opentelemetry/semconv/templating/code.py b/semantic-conventions/src/opentelemetry/semconv/templating/code.py index b84a39fd..cc685273 100644 --- a/semantic-conventions/src/opentelemetry/semconv/templating/code.py +++ b/semantic-conventions/src/opentelemetry/semconv/templating/code.py @@ -22,9 +22,13 @@ from opentelemetry.semconv.model.semantic_attribute import ( RequirementLevel, + SemanticAttribute, TextWithLinks, ) -from opentelemetry.semconv.model.semantic_convention import SemanticConventionSet +from opentelemetry.semconv.model.semantic_convention import ( + SemanticConvention, + SemanticConventionSet, +) from opentelemetry.semconv.model.utils import ID_RE @@ -156,6 +160,10 @@ def to_camelcase(name: str, first_upper=False) -> str: return first + "".join(word.capitalize() for word in rest) +def is_deprecated(obj: typing.Union[SemanticAttribute, SemanticConvention]) -> bool: + return obj.deprecated is not None + + class CodeRenderer: pattern = f"{{{ID_RE.pattern}}}" @@ -209,6 +217,8 @@ def setup_environment(env: Environment, trim_whitespace: bool): env.filters["to_html_links"] = to_html_links env.filters["regex_replace"] = regex_replace env.filters["render_markdown"] = render_markdown + env.filters["is_deprecated"] = is_deprecated + env.tests["is_deprecated"] = is_deprecated env.trim_blocks = trim_whitespace env.lstrip_blocks = trim_whitespace diff --git a/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py b/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py index 64c8b744..f708f168 100644 --- a/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py +++ b/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py @@ -119,19 +119,19 @@ def to_markdown_attr( if "deprecated" in attribute.deprecated.lower(): description = f"**{attribute.deprecated}**
" else: - deprecated_msg = self.options.md_snippet_by_stability_level[ - StabilityLevel.DEPRECATED - ].format(attribute.deprecated) + deprecated_msg = self.options.deprecated_md_snippet().format( + attribute.deprecated + ) description = f"{deprecated_msg}
" elif ( attribute.stability == StabilityLevel.STABLE and self.options.enable_stable ): - description = f"{self.options.md_snippet_by_stability_level[StabilityLevel.STABLE]}
" + description = f"{self.options.stable_md_snippet()}
" elif ( attribute.stability == StabilityLevel.EXPERIMENTAL and self.options.enable_experimental ): - description = f"{self.options.md_snippet_by_stability_level[StabilityLevel.EXPERIMENTAL]}
" + description = f"{self.options.experimental_md_snippet}
" description += attribute.brief if attribute.note: self.render_ctx.add_note(attribute.note) diff --git a/semantic-conventions/src/opentelemetry/semconv/templating/markdown/options.py b/semantic-conventions/src/opentelemetry/semconv/templating/markdown/options.py index 64dd6848..f053ddbe 100644 --- a/semantic-conventions/src/opentelemetry/semconv/templating/markdown/options.py +++ b/semantic-conventions/src/opentelemetry/semconv/templating/markdown/options.py @@ -20,19 +20,6 @@ @dataclass() class MarkdownOptions: - - _badge_map = { - StabilityLevel.DEPRECATED: "![Deprecated](https://img.shields.io/badge/-deprecated-red)", - StabilityLevel.EXPERIMENTAL: "![Experimental](https://img.shields.io/badge/-experimental-blue)", - StabilityLevel.STABLE: "![Stable](https://img.shields.io/badge/-stable-lightgreen)", - } - - _label_map = { - StabilityLevel.DEPRECATED: "**Deprecated: {}**", - StabilityLevel.EXPERIMENTAL: "**Experimental**", - StabilityLevel.STABLE: "**Stable**", - } - check_only: bool = False enable_stable: bool = False enable_experimental: bool = False @@ -41,8 +28,17 @@ class MarkdownOptions: break_count: int = 50 exclude_files: List[str] = field(default_factory=list) - @property - def md_snippet_by_stability_level(self): + def stable_md_snippet(self): + if self.use_badge: + return "![Stable](https://img.shields.io/badge/-stable-lightgreen)" + return "**Stable**" + + def experimental_md_snippet(self): + if self.use_badge: + return "![Experimental](https://img.shields.io/badge/-experimental-blue)" + return "**Experimental**" + + def deprecated_md_snippet(self): if self.use_badge: - return self._badge_map - return self._label_map + return "![Deprecated](https://img.shields.io/badge/-deprecated-red)" + return "**Deprecated: {}**" diff --git a/semantic-conventions/src/tests/data/jinja/attribute_templates/template b/semantic-conventions/src/tests/data/jinja/attribute_templates/template index 486ddce2..e32d00a3 100644 --- a/semantic-conventions/src/tests/data/jinja/attribute_templates/template +++ b/semantic-conventions/src/tests/data/jinja/attribute_templates/template @@ -49,12 +49,12 @@ class AttributesTemplate { *

Notes:

{%- endif %} - {%- if (attribute_template.stability | string()) == "StabilityLevel.DEPRECATED" %} + {%- if attribute_template | is_deprecated %} * * @deprecated {{attribute_template.brief | to_doc_brief}}. {%- endif %} */ - {%- if (attribute_template.stability | string()) == "StabilityLevel.DEPRECATED" %} + {%- if attribute_template | is_deprecated %} @Deprecated {%- endif %} public static final AttributeKey<{{upFirst(to_java_return_type(attribute_template.instantiated_type | string))}}> {{attribute_template.fqn | to_const_name}} = {{to_java_key_type(attribute_template.instantiated_type | string)}}("{{attribute_template.fqn}}"); @@ -68,12 +68,12 @@ class AttributesTemplate { *

Notes:

{%- endif %} - {%- if (attribute.stability | string()) == "StabilityLevel.DEPRECATED" %} + {%- if attribute | is_deprecated %} * * @deprecated {{attribute.brief | to_doc_brief}}. {%- endif %} */ - {%- if (attribute.stability | string()) == "StabilityLevel.DEPRECATED" %} + {%- if attribute | is_deprecated %} @Deprecated {%- endif %} public static final AttributeKey<{{upFirst(to_java_return_type(attribute.instantiated_type | string))}}> {{attribute.fqn | to_const_name}} = {{to_java_key_type(attribute.instantiated_type | string)}}("{{attribute.fqn}}"); diff --git a/semantic-conventions/src/tests/data/markdown/stability/badges_expected.md b/semantic-conventions/src/tests/data/markdown/stability/badges_expected.md index 28196f68..de1439da 100644 --- a/semantic-conventions/src/tests/data/markdown/stability/badges_expected.md +++ b/semantic-conventions/src/tests/data/markdown/stability/badges_expected.md @@ -4,7 +4,7 @@ | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| | [`test.def_stability`](labels_expected.md) | boolean | | | Required | -| [`test.deprecated_attr`](labels_expected.md) | boolean | | | Required | +| [`test.deprecated_attr`](labels_expected.md) | boolean | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
| | Required | | [`test.exp_attr`](labels_expected.md) | boolean | | | Required | | [`test.stable_attr`](labels_expected.md) | boolean | ![Stable](https://img.shields.io/badge/-stable-lightgreen)
| | Required | diff --git a/semantic-conventions/src/tests/data/markdown/stability/labels_expected.md b/semantic-conventions/src/tests/data/markdown/stability/labels_expected.md index 2ae182e2..ab7f6194 100644 --- a/semantic-conventions/src/tests/data/markdown/stability/labels_expected.md +++ b/semantic-conventions/src/tests/data/markdown/stability/labels_expected.md @@ -4,7 +4,7 @@ | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| | [`test.def_stability`](labels_expected.md) | boolean | | | Required | -| [`test.deprecated_attr`](labels_expected.md) | boolean | | | Required | +| [`test.deprecated_attr`](labels_expected.md) | boolean | **Deprecated: Removed.**
| | Required | | [`test.exp_attr`](labels_expected.md) | boolean | | | Required | | [`test.stable_attr`](labels_expected.md) | boolean | | | Required | diff --git a/semantic-conventions/src/tests/data/markdown/stability/stability.yaml b/semantic-conventions/src/tests/data/markdown/stability/stability.yaml index d8c78c32..14ed4783 100644 --- a/semantic-conventions/src/tests/data/markdown/stability/stability.yaml +++ b/semantic-conventions/src/tests/data/markdown/stability/stability.yaml @@ -17,7 +17,8 @@ groups: - id: deprecated_attr type: boolean requirement_level: required - stability: deprecated + stability: stable + deprecated: "Removed." brief: "" - id: def_stability type: boolean diff --git a/semantic-conventions/src/tests/data/yaml/errors/stability/stability_deprecated.yaml b/semantic-conventions/src/tests/data/yaml/errors/stability/stability_deprecated.yaml deleted file mode 100644 index 8586f9fb..00000000 --- a/semantic-conventions/src/tests/data/yaml/errors/stability/stability_deprecated.yaml +++ /dev/null @@ -1,13 +0,0 @@ -groups: - - id: test - type: span - brief: 'test' - prefix: http - attributes: - - id: test_attr - type: boolean - requirement_level: required - stability: stable - deprecated: should fail. - brief: "" - diff --git a/semantic-conventions/src/tests/data/yaml/errors/stability/wrong_value.yaml b/semantic-conventions/src/tests/data/yaml/errors/stability/wrong_value.yaml index b8bfde6d..2e8845ff 100644 --- a/semantic-conventions/src/tests/data/yaml/errors/stability/wrong_value.yaml +++ b/semantic-conventions/src/tests/data/yaml/errors/stability/wrong_value.yaml @@ -9,4 +9,3 @@ groups: requirement_level: required stability: will_fail brief: "" - diff --git a/semantic-conventions/src/tests/data/yaml/stability.yaml b/semantic-conventions/src/tests/data/yaml/stability.yaml index 45187e54..48631cc7 100644 --- a/semantic-conventions/src/tests/data/yaml/stability.yaml +++ b/semantic-conventions/src/tests/data/yaml/stability.yaml @@ -2,7 +2,7 @@ groups: - id: test type: span brief: 'test' - prefix: http + prefix: http_1 attributes: - id: exp_attr type: boolean @@ -14,11 +14,6 @@ groups: requirement_level: required stability: stable brief: "" - - id: deprecated_attr - type: boolean - requirement_level: required - stability: deprecated - brief: "" - id: def_stability type: boolean requirement_level: required @@ -27,7 +22,7 @@ groups: - id: parent_default type: span brief: 'test' - prefix: http + prefix: http_2 stability: experimental attributes: - id: test_attr @@ -43,19 +38,25 @@ groups: - id: not_fail type: span brief: 'test' - prefix: http - stability: deprecated + prefix: http_3 + stability: experimental attributes: - id: test_attr type: boolean requirement_level: required deprecated: should not fail. brief: "" + - id: stable_deprecated_attr + type: boolean + requirement_level: required + stability: stable + deprecated: "should not fail." + brief: "" - id: resource_test type: resource brief: 'test' - prefix: http + prefix: http_4 attributes: - id: exp_attr type: boolean @@ -67,11 +68,6 @@ groups: requirement_level: required stability: stable brief: "" - - id: deprecated_attr - type: boolean - requirement_level: required - stability: deprecated - brief: "" - id: def_stability type: boolean requirement_level: required @@ -80,7 +76,7 @@ groups: - id: resource_parent_default type: resource brief: 'test' - prefix: http + prefix: http_5 stability: experimental attributes: - id: test_attr @@ -96,8 +92,7 @@ groups: - id: resource_not_fail type: resource brief: 'test' - prefix: http - stability: deprecated + prefix: http_6 attributes: - id: test_attr type: boolean 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 11597797..e1d0f0f4 100644 --- a/semantic-conventions/src/tests/semconv/model/test_correct_parse.py +++ b/semantic-conventions/src/tests/semconv/model/test_correct_parse.py @@ -476,22 +476,18 @@ def test_stability(self): self.assertEqual(len(semconv.models), 6) model = list(semconv.models.values())[0] - self.assertEqual(len(model.attributes_and_templates), 4) - self.assertEqual(model.stability, None) + self.assertEqual(len(model.attributes_and_templates), 3) + self.assertEqual(model.stability, StabilityLevel.EXPERIMENTAL) attr = model.attributes_and_templates[0] self.assertEqual(attr.attr_id, "def_stability") self.assertEqual(attr.stability, StabilityLevel.EXPERIMENTAL) attr = model.attributes_and_templates[1] - self.assertEqual(attr.attr_id, "deprecated_attr") - self.assertEqual(attr.stability, StabilityLevel.DEPRECATED) - - attr = model.attributes_and_templates[2] self.assertEqual(attr.attr_id, "exp_attr") self.assertEqual(attr.stability, StabilityLevel.EXPERIMENTAL) - attr = model.attributes_and_templates[3] + attr = model.attributes_and_templates[2] self.assertEqual(attr.attr_id, "stable_attr") self.assertEqual(attr.stability, StabilityLevel.STABLE) @@ -501,19 +497,24 @@ def test_stability(self): attr = model.attributes_and_templates[0] self.assertEqual(attr.attr_id, "dep") - self.assertEqual(attr.stability, StabilityLevel.DEPRECATED) + self.assertEqual(attr.stability, StabilityLevel.EXPERIMENTAL) attr = model.attributes_and_templates[1] self.assertEqual(attr.attr_id, "test_attr") self.assertEqual(attr.stability, StabilityLevel.EXPERIMENTAL) model = list(semconv.models.values())[2] - self.assertEqual(len(model.attributes_and_templates), 1) - self.assertEqual(model.stability, StabilityLevel.DEPRECATED) + self.assertEqual(len(model.attributes_and_templates), 2) + self.assertEqual(model.stability, StabilityLevel.EXPERIMENTAL) attr = model.attributes_and_templates[0] + self.assertEqual(attr.attr_id, "stable_deprecated_attr") + self.assertEqual(attr.stability, StabilityLevel.STABLE) + self.assertIsNotNone(attr.deprecated) + + attr = model.attributes_and_templates[1] self.assertEqual(attr.attr_id, "test_attr") - self.assertEqual(attr.stability, StabilityLevel.DEPRECATED) + self.assertEqual(attr.stability, StabilityLevel.EXPERIMENTAL) def test_populate_other_attributes(self): semconv = SemanticConventionSet(debug=False) diff --git a/semantic-conventions/src/tests/semconv/model/test_error_detection.py b/semantic-conventions/src/tests/semconv/model/test_error_detection.py index 7d53a3a6..af1c9132 100644 --- a/semantic-conventions/src/tests/semconv/model/test_error_detection.py +++ b/semantic-conventions/src/tests/semconv/model/test_error_detection.py @@ -141,25 +141,14 @@ def test_invalid_stability(self): self.assertIn("is not allowed as a stability marker", msg) self.assertEqual(e.line, 10) - def test_invalid_stability_with_deprecated(self): - with self.assertRaises(ValidationError) as ex: - self.open_yaml("yaml/errors/stability/stability_deprecated.yaml") - self.fail() - e = ex.exception - msg = e.message.lower() - self.assertIn("there is a deprecation message but the stability is set to", msg) - self.assertEqual(e.line, 11) - def test_invalid_semconv_stability_with_deprecated(self): with self.assertRaises(ValidationError) as ex: self.open_yaml("yaml/errors/stability/semconv_stability_deprecated.yaml") self.fail() e = ex.exception msg = e.message.lower() - self.assertIn( - "semantic convention stability set to deprecated but attribute", msg - ) - self.assertEqual(e.line, 11) + self.assertIn("value 'deprecated' is not allowed as a stability marker", msg) + self.assertEqual(e.line, 6) def test_invalid_deprecated_empty_string(self): with self.assertRaises(ValidationError) as ex: diff --git a/semantic-conventions/src/tests/semconv/model/test_semantic_attribute.py b/semantic-conventions/src/tests/semconv/model/test_semantic_attribute.py index 63466ca4..9a8ef067 100644 --- a/semantic-conventions/src/tests/semconv/model/test_semantic_attribute.py +++ b/semantic-conventions/src/tests/semconv/model/test_semantic_attribute.py @@ -19,7 +19,7 @@ def test_parse(load_yaml): yaml = load_yaml("semantic_attributes.yml") - attributes = SemanticAttribute.parse("prefix", "", yaml.get("attributes")) + attributes = SemanticAttribute.parse("prefix", yaml.get("attributes")) assert len(attributes) == 3 @@ -45,7 +45,7 @@ def test_parse(load_yaml): def test_parse_deprecated(load_yaml): yaml = load_yaml("semantic_attributes_deprecated.yml") - attributes = SemanticAttribute.parse("", "", yaml.get("attributes")) + attributes = SemanticAttribute.parse("", yaml.get("attributes")) assert len(attributes) == 1 assert list(attributes.keys()) == ["deprecated_attribute"] @@ -62,7 +62,7 @@ def test_parse_regex(): def test_parse_attribute_templates(load_yaml): yaml = load_yaml("attribute_templates.yml") - attribute_templates = SemanticAttribute.parse("prefix", "", yaml.get("attributes")) + attribute_templates = SemanticAttribute.parse("prefix", yaml.get("attributes")) assert len(attribute_templates) == 3 diff --git a/semantic-conventions/syntax.md b/semantic-conventions/syntax.md index adcfdc73..a422b309 100644 --- a/semantic-conventions/syntax.md +++ b/semantic-conventions/syntax.md @@ -62,8 +62,7 @@ prefix ::= string extends ::= string -stability ::= "deprecated" - | "experimental" +stability ::= "experimental" | "stable" deprecated ::= @@ -135,10 +134,10 @@ name ::= string metricfields ::= metric_name instrument unit metric_name ::= string -instrument ::= "counter" - | "histogram" - | "gauge" - | "updowncounter" +instrument ::= "counter" + | "histogram" + | "gauge" + | "updowncounter" unit ::= string ``` @@ -161,13 +160,9 @@ The field `semconv` represents a semantic convention and it is made by: It defaults to an empty string. - `extends`, optional string, reference another semantic convention `id`. It inherits the prefix, constraints, and all attributes defined in the specified semantic convention. -- `stability`, optional enum, specifies the stability of the semantic convention. - - Note that, if `stability` is missing but `deprecated` is present, it will automatically set the `stability` to `deprecated`. - If `deprecated` is present and `stability` differs from `deprecated`, this will result in an error. -- `deprecated`, optional, specifies if the semantic convention is deprecated. +- `stability`, optional enum, specifies the stability of the semantic convention. Defaults to `experimental`. +- `deprecated`, optional, when present marks the semantic convention as deprecated. The string provided as `` MUST specify why it's deprecated and/or what to use instead. - See also `stability`. - `attributes`, list of attributes that belong to the semantic convention. - `constraints`, optional list, additional constraints (See later). It defaults to an empty list. @@ -189,27 +184,27 @@ The following is only valid if `type` is `event`: #### Metric Group semantic convention -Metric group inherits all from the base semantic convention, and does not +Metric group inherits all from the base semantic convention, and does not add any additional fields. -The metric group semconv is a group where related metric attributes +The metric group semconv is a group where related metric attributes can be defined and then referenced from other `metric` groups using `ref`. #### Metric semantic convention The following is only valid if `type` is `metric`: - - `metric_name`, required, the metric name as described by the [OpenTelemetry Specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/data-model.md#timeseries-model). - - `instrument`, required, the [instrument type]( https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument) - that should be used to record the metric. Note that the semantic conventions must be written + - `metric_name`, required, the metric name as described by the [OpenTelemetry Specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/data-model.md#timeseries-model). + - `instrument`, required, the [instrument type]( https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument) + that should be used to record the metric. Note that the semantic conventions must be written using the names of the synchronous instrument types (`counter`, `gauge`, `updowncounter` and `histogram`). For more details: [Metrics semantic conventions - Instrument types](https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/metrics/semantic_conventions#instrument-types). - - `unit`, required, the unit in which the metric is measured, which should adhere to - [the guidelines](https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/metrics/semantic_conventions#instrument-units). + - `unit`, required, the unit in which the metric is measured, which should adhere to + [the guidelines](https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/metrics/semantic_conventions#instrument-units). #### Attribute group semantic convention -Attribute group (`attribute_group` type) defines a set of attributes that can be +Attribute group (`attribute_group` type) defines a set of attributes that can be declared once and referenced by semantic conventions for different signals, for example spans and logs. Attribute groups don't have any specific fields and follow the general `semconv` semantics. @@ -339,7 +334,7 @@ fields are present in the current attribute definition, they override the inheri #### Type An attribute type can either be a string, int, double, boolean, array of strings, array of int, array of double, -array of booleans, a template type or an enumeration. +array of booleans, a template type or an enumeration. ##### Template type @@ -347,7 +342,7 @@ A template type attribute represents a _dictionary_ of attributes with a common `type: template[]` -The `` is one of the above-mentioned primitive or array types (_not_ an enum) and specifies the type of the `value` in the dictionary. +The `` is one of the above-mentioned primitive or array types (_not_ an enum) and specifies the type of the `value` in the dictionary. The following is an example for defining a template type attribute and it's resolution: @@ -366,7 +361,7 @@ groups: ... ``` -In this example the definition will be resolved into a dictionary of attributes `http.request.header.` where `` will be replaced by the actual HTTP header name, and the value of the attributes is of type `string[]` that carries the HTTP header value. +In this example the definition will be resolved into a dictionary of attributes `http.request.header.` where `` will be replaced by the actual HTTP header name, and the value of the attributes is of type `string[]` that carries the HTTP header value. ##### Enumeration From bd6b27bb5eb1e3afc599d3dd52a00df7cdaec66c Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Wed, 6 Dec 2023 20:37:50 -0800 Subject: [PATCH 2/4] changelog --- semantic-conventions/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/semantic-conventions/CHANGELOG.md b/semantic-conventions/CHANGELOG.md index 3ee1a580..8b74cb31 100644 --- a/semantic-conventions/CHANGELOG.md +++ b/semantic-conventions/CHANGELOG.md @@ -4,8 +4,8 @@ Please update the changelog as part of any significant pull request. ## Unreleased -- BREAKING: Make stability and deprecation independent attribute and semantic convention properties. - ([#](https://github.com/open-telemetry/build-tools/pull/TODO)) +- BREAKING: Make stability and deprecation independent properties. + ([#244](https://github.com/open-telemetry/build-tools/pull/244)) ## v0.23.0 From ef1f6668ee1312a66ae0fa3c151b0a1bbfb0d1eb Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Wed, 6 Dec 2023 20:44:10 -0800 Subject: [PATCH 3/4] lint --- .../src/opentelemetry/semconv/templating/code.py | 4 ++-- .../src/opentelemetry/semconv/templating/markdown/options.py | 2 -- .../src/tests/data/yaml/errors/stability/wrong_value.yaml | 1 + 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/semantic-conventions/src/opentelemetry/semconv/templating/code.py b/semantic-conventions/src/opentelemetry/semconv/templating/code.py index cc685273..b8865291 100644 --- a/semantic-conventions/src/opentelemetry/semconv/templating/code.py +++ b/semantic-conventions/src/opentelemetry/semconv/templating/code.py @@ -26,7 +26,7 @@ TextWithLinks, ) from opentelemetry.semconv.model.semantic_convention import ( - SemanticConvention, + BaseSemanticConvention, SemanticConventionSet, ) from opentelemetry.semconv.model.utils import ID_RE @@ -160,7 +160,7 @@ def to_camelcase(name: str, first_upper=False) -> str: return first + "".join(word.capitalize() for word in rest) -def is_deprecated(obj: typing.Union[SemanticAttribute, SemanticConvention]) -> bool: +def is_deprecated(obj: typing.Union[SemanticAttribute, BaseSemanticConvention]) -> bool: return obj.deprecated is not None diff --git a/semantic-conventions/src/opentelemetry/semconv/templating/markdown/options.py b/semantic-conventions/src/opentelemetry/semconv/templating/markdown/options.py index f053ddbe..419ef8f1 100644 --- a/semantic-conventions/src/opentelemetry/semconv/templating/markdown/options.py +++ b/semantic-conventions/src/opentelemetry/semconv/templating/markdown/options.py @@ -15,8 +15,6 @@ from dataclasses import dataclass, field from typing import List -from opentelemetry.semconv.model.semantic_attribute import StabilityLevel - @dataclass() class MarkdownOptions: diff --git a/semantic-conventions/src/tests/data/yaml/errors/stability/wrong_value.yaml b/semantic-conventions/src/tests/data/yaml/errors/stability/wrong_value.yaml index 2e8845ff..b8bfde6d 100644 --- a/semantic-conventions/src/tests/data/yaml/errors/stability/wrong_value.yaml +++ b/semantic-conventions/src/tests/data/yaml/errors/stability/wrong_value.yaml @@ -9,3 +9,4 @@ groups: requirement_level: required stability: will_fail brief: "" + From 0f74ebb145fb4759577a605c5cc1162ba76447d1 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Thu, 7 Dec 2023 09:18:10 -0800 Subject: [PATCH 4/4] up --- .../src/opentelemetry/semconv/templating/markdown/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py b/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py index f708f168..3590502c 100644 --- a/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py +++ b/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py @@ -131,7 +131,7 @@ def to_markdown_attr( attribute.stability == StabilityLevel.EXPERIMENTAL and self.options.enable_experimental ): - description = f"{self.options.experimental_md_snippet}
" + description = f"{self.options.experimental_md_snippet()}
" description += attribute.brief if attribute.note: self.render_ctx.add_note(attribute.note)