diff --git a/semantic-conventions/CHANGELOG.md b/semantic-conventions/CHANGELOG.md index e608dace..0e9f05d6 100644 --- a/semantic-conventions/CHANGELOG.md +++ b/semantic-conventions/CHANGELOG.md @@ -8,6 +8,8 @@ Please update the changelog as part of any significant pull request. [BREAKING] The `--file-per-group ` that used to create multiple directories (like `output//file`) now generates multiple files (`output/file`) instead. ([#243](https://github.com/open-telemetry/build-tools/pull/243)) +- BREAKING: Make stability and deprecation independent properties. + ([#244](https://github.com/open-telemetry/build-tools/pull/244)) ## v0.23.0 diff --git a/semantic-conventions/src/opentelemetry/semconv/model/semantic_attribute.py b/semantic-conventions/src/opentelemetry/semconv/model/semantic_attribute.py index f22a9bbd..4f603846 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 @@ -83,9 +82,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. """ @@ -180,21 +177,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") @@ -297,43 +286,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 + def parse_stability(stability, position_data): + if stability is None: + return StabilityLevel.EXPERIMENTAL - @staticmethod - def check_stability(stability_value, position): 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 9aafb1c8..ef084f41 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 91b59e32..721a8462 100644 --- a/semantic-conventions/src/opentelemetry/semconv/templating/code.py +++ b/semantic-conventions/src/opentelemetry/semconv/templating/code.py @@ -190,7 +190,7 @@ def is_stable(obj: typing.Union[SemanticAttribute, BaseSemanticConvention]) -> b def is_deprecated(obj: typing.Union[SemanticAttribute, BaseSemanticConvention]) -> bool: - return obj.stability == StabilityLevel.DEPRECATED + return obj.deprecated is not None def is_experimental( diff --git a/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py b/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py index 64c8b744..3590502c 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..419ef8f1 100644 --- a/semantic-conventions/src/opentelemetry/semconv/templating/markdown/options.py +++ b/semantic-conventions/src/opentelemetry/semconv/templating/markdown/options.py @@ -15,24 +15,9 @@ from dataclasses import dataclass, field from typing import List -from opentelemetry.semconv.model.semantic_attribute import StabilityLevel - @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 +26,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 d320e990..c6b139df 100644 --- a/semantic-conventions/src/tests/data/jinja/attribute_templates/template +++ b/semantic-conventions/src/tests/data/jinja/attribute_templates/template @@ -45,7 +45,7 @@ class AttributesTemplate { * @deprecated {{attribute_template.brief | to_doc_brief}}. {%- endif %} */ - {%- if attribute_template | is_deprecated %} + {%- if attribute_template | is_deprecated %} @Deprecated {%- endif %} public static final AttributeKey<{{ to_java_return_type(attribute_template.instantiated_type | string) | to_camelcase(True)}}> {{attribute_template.fqn | to_const_name}} = {{to_java_key_type(attribute_template.instantiated_type | string)}}("{{attribute_template.fqn}}"); @@ -64,7 +64,7 @@ class AttributesTemplate { * @deprecated {{attribute.brief | to_doc_brief}}. {%- endif %} */ - {%- if attribute | is_deprecated %} + {%- if attribute | is_deprecated %} @Deprecated {%- endif %} public static final AttributeKey<{{ to_java_return_type(attribute.instantiated_type | string) | to_camelcase(True)}}> {{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/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