From ddb6f21ec6d69f4fab7d2601f4366f6cdd984246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Neum=C3=BCller?= Date: Wed, 15 Sep 2021 17:06:27 +0200 Subject: [PATCH 1/5] Fix leading dot in FQN of attribute w/o prefix. --- .../src/opentelemetry/semconv/model/semantic_attribute.py | 5 ++++- .../src/tests/semconv/model/test_semantic_attribute.py | 6 ++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/semantic-conventions/src/opentelemetry/semconv/model/semantic_attribute.py b/semantic-conventions/src/opentelemetry/semconv/model/semantic_attribute.py index 9ca6f609..cb5e6920 100644 --- a/semantic-conventions/src/opentelemetry/semconv/model/semantic_attribute.py +++ b/semantic-conventions/src/opentelemetry/semconv/model/semantic_attribute.py @@ -117,7 +117,10 @@ def parse( if attr_id is not None: validate_id(attr_id, position_data["id"]) attr_type, brief, examples = SemanticAttribute.parse_id(attribute) - fqn = "{}.{}".format(prefix, attr_id) + if prefix: + fqn = "{}.{}".format(prefix, attr_id) + else: + fqn = attr_id else: # Ref attr_type = None 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 1fb85470..db614cfb 100644 --- a/semantic-conventions/src/tests/semconv/model/test_semantic_attribute.py +++ b/semantic-conventions/src/tests/semconv/model/test_semantic_attribute.py @@ -46,8 +46,6 @@ def test_parse_deprecated(load_yaml): attributes = SemanticAttribute.parse("", "", yaml.get("attributes")) assert len(attributes) == 1 - assert list(attributes.keys()) == [".deprecated_attribute"] + assert list(attributes.keys()) == ["deprecated_attribute"] - assert ( - attributes[".deprecated_attribute"].deprecated == "don't use this one anymore" - ) + assert attributes["deprecated_attribute"].deprecated == "don't use this one anymore" From cc40f7efc4921b9004be2bd63c061933dbc1ef37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Neum=C3=BCller?= Date: Wed, 15 Sep 2021 16:42:32 +0200 Subject: [PATCH 2/5] Add event name field. --- semantic-conventions/semconv.schema.json | 22 +++++- .../semconv/model/semantic_convention.py | 59 +++++++--------- .../semconv/templating/markdown/__init__.py | 9 ++- .../src/tests/data/markdown/event/expected.md | 4 +- .../src/tests/data/markdown/event/input.md | 2 +- .../data/markdown/event_noprefix/event.yaml | 9 +++ .../data/markdown/event_noprefix/expected.md | 9 +++ .../data/markdown/event_noprefix/input.md | 5 ++ .../yaml/errors/events/nameless_event.yaml | 8 +++ .../semconv/model/test_error_detection.py | 8 +++ .../tests/semconv/templating/test_markdown.py | 3 + semantic-conventions/syntax.md | 67 ++++++++++++------- 12 files changed, 142 insertions(+), 63 deletions(-) create mode 100644 semantic-conventions/src/tests/data/markdown/event_noprefix/event.yaml create mode 100644 semantic-conventions/src/tests/data/markdown/event_noprefix/expected.md create mode 100644 semantic-conventions/src/tests/data/markdown/event_noprefix/input.md create mode 100644 semantic-conventions/src/tests/data/yaml/errors/events/nameless_event.yaml diff --git a/semantic-conventions/semconv.schema.json b/semantic-conventions/semconv.schema.json index 86ba3c28..c1918e8c 100644 --- a/semantic-conventions/semconv.schema.json +++ b/semantic-conventions/semconv.schema.json @@ -13,6 +13,9 @@ }, { "allOf": [{"$ref": "#/definitions/SpanSemanticConvention"}] + }, + { + "allOf": [{"$ref": "#/definitions/EventSemanticConvention"}] } ] } @@ -143,6 +146,23 @@ } } }, + "EventSemanticConvention": { + "allOf": [{ "$ref": "#/definitions/SemanticConventionBase" }], + "properties": { + "type": { + "type": "string", + "const": "event" + }, + "name": { + "type": "string", + "description": "The name of the event. Required if no prefix is given." + } + }, + "anyOf": [ + {"required": ["prefix"]}, + {"required": ["name"]} + ] + }, "SemanticConvention": { "allOf": [{ "$ref": "#/definitions/SemanticConventionBase" }], "required": ["type"], @@ -150,7 +170,7 @@ "type": { "type": "string", "not": { - "const": "span" + "enum": ["span", "event"] } } } diff --git a/semantic-conventions/src/opentelemetry/semconv/model/semantic_convention.py b/semantic-conventions/src/opentelemetry/semconv/model/semantic_convention.py index dc51ee60..bde3ccff 100644 --- a/semantic-conventions/src/opentelemetry/semconv/model/semantic_convention.py +++ b/semantic-conventions/src/opentelemetry/semconv/model/semantic_convention.py @@ -15,7 +15,7 @@ import sys from dataclasses import dataclass, field from enum import Enum -from typing import Union +from typing import Tuple, Union import typing from ruamel.yaml import YAML @@ -99,6 +99,18 @@ def SemanticConvention(group): class BaseSemanticConvention(ValidatableYamlNode): """Contains the model extracted from a yaml file""" + allowed_keys: Tuple[str, ...] = ( + "id", + "type", + "brief", + "note", + "prefix", + "stability", + "extends", + "attributes", + "constraints", + ) + GROUP_TYPE_NAME: str @property @@ -179,34 +191,13 @@ def validate_values(self): class ResourceSemanticConvention(BaseSemanticConvention): GROUP_TYPE_NAME = "resource" - allowed_keys = ( - "id", - "type", - "brief", - "note", - "prefix", - "stability", - "extends", - "attributes", - "constraints", - ) - class SpanSemanticConvention(BaseSemanticConvention): GROUP_TYPE_NAME = "span" - allowed_keys = ( - "id", - "type", - "brief", - "note", - "prefix", - "stability", - "extends", + allowed_keys = BaseSemanticConvention.allowed_keys + ( "events", "span_kind", - "attributes", - "constraints", ) def __init__(self, group): @@ -221,23 +212,21 @@ def __init__(self, group): class EventSemanticConvention(BaseSemanticConvention): GROUP_TYPE_NAME = "event" - allowed_keys = ( - "id", - "type", - "brief", - "note", - "prefix", - "stability", - "extends", - "attributes", - "constraints", - ) + allowed_keys = BaseSemanticConvention.allowed_keys + ("name",) + + def __init__(self, group): + super().__init__(group) + self.name = group.get("name", self.prefix) + if not self.name: + raise ValidationError.from_yaml_pos( + self._position, "Event must define at least one of name or prefix" + ) class UnitSemanticConvention(BaseSemanticConvention): GROUP_TYPE_NAME = "units" - allowed_keys = ( + allowed_keys = ( # We completely override base semantic keys here. "id", "type", "brief", diff --git a/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py b/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py index 723da8b5..0410dcec 100644 --- a/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py +++ b/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py @@ -29,6 +29,7 @@ EnumMember, ) from opentelemetry.semconv.model.semantic_convention import ( + EventSemanticConvention, SemanticConventionSet, UnitSemanticConvention, ) @@ -375,14 +376,14 @@ def _render_single_file(self, content: str, md: str, output: io.StringIO): "Semantic Convention ID {} not found".format(semconv_id) ) output.write(content[last_match : match.start(0)]) - self._render_table(semconv, parameters, output) + self._render_group(semconv, parameters, output) end_match = self.p_end.search(content, last_match) if not end_match: raise ValueError("Missing ending tag") last_match = end_match.end() output.write(content[last_match:]) - def _render_table(self, semconv, parameters, output): + def _render_group(self, semconv, parameters, output): header: str header = semconv.semconv_id if parameters: @@ -397,6 +398,10 @@ def _render_table(self, semconv, parameters, output): self.render_ctx.is_remove_constraint = "remove_constraints" in parameters self.render_ctx.group_key = parameters.get("tag") self.render_ctx.is_full = "full" in parameters + + if isinstance(semconv, EventSemanticConvention): + output.write("The event name MUST be `{}`.\n\n".format(semconv.name)) + attr_to_print = [] attr: SemanticAttribute for attr in sorted( diff --git a/semantic-conventions/src/tests/data/markdown/event/expected.md b/semantic-conventions/src/tests/data/markdown/event/expected.md index 7d4e5055..b03aadef 100644 --- a/semantic-conventions/src/tests/data/markdown/event/expected.md +++ b/semantic-conventions/src/tests/data/markdown/event/expected.md @@ -1,6 +1,8 @@ # Test +The event name MUST be `exception`. + | Attribute | Type | Description | Examples | Required | |---|---|---|---|---| | `exception.type` | string | The type of the exception. | `java.net.ConnectException`; `OSError` | See below | @@ -14,4 +16,4 @@ * `exception.type` * `exception.message` - \ No newline at end of file + diff --git a/semantic-conventions/src/tests/data/markdown/event/input.md b/semantic-conventions/src/tests/data/markdown/event/input.md index 59862542..69adbf92 100644 --- a/semantic-conventions/src/tests/data/markdown/event/input.md +++ b/semantic-conventions/src/tests/data/markdown/event/input.md @@ -2,4 +2,4 @@ - \ No newline at end of file + diff --git a/semantic-conventions/src/tests/data/markdown/event_noprefix/event.yaml b/semantic-conventions/src/tests/data/markdown/event_noprefix/event.yaml new file mode 100644 index 00000000..3e41bf3c --- /dev/null +++ b/semantic-conventions/src/tests/data/markdown/event_noprefix/event.yaml @@ -0,0 +1,9 @@ +groups: + - id: event + name: myname + type: event + brief: brief + attributes: + - id: attr + type: boolean + brief: attrbrief diff --git a/semantic-conventions/src/tests/data/markdown/event_noprefix/expected.md b/semantic-conventions/src/tests/data/markdown/event_noprefix/expected.md new file mode 100644 index 00000000..560912f5 --- /dev/null +++ b/semantic-conventions/src/tests/data/markdown/event_noprefix/expected.md @@ -0,0 +1,9 @@ +# Test + + +The event name MUST be `myname`. + +| Attribute | Type | Description | Examples | Required | +|---|---|---|---|---| +| `attr` | boolean | attrbrief | | No | + diff --git a/semantic-conventions/src/tests/data/markdown/event_noprefix/input.md b/semantic-conventions/src/tests/data/markdown/event_noprefix/input.md new file mode 100644 index 00000000..69adbf92 --- /dev/null +++ b/semantic-conventions/src/tests/data/markdown/event_noprefix/input.md @@ -0,0 +1,5 @@ +# Test + + + + diff --git a/semantic-conventions/src/tests/data/yaml/errors/events/nameless_event.yaml b/semantic-conventions/src/tests/data/yaml/errors/events/nameless_event.yaml new file mode 100644 index 00000000..60830869 --- /dev/null +++ b/semantic-conventions/src/tests/data/yaml/errors/events/nameless_event.yaml @@ -0,0 +1,8 @@ +groups: + - id: eventid + type: event + brief: eventbrief + attributes: + - id: eventattr + type: boolean + brief: eventattrbrief 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 1a160309..76ba2928 100644 --- a/semantic-conventions/src/tests/semconv/model/test_error_detection.py +++ b/semantic-conventions/src/tests/semconv/model/test_error_detection.py @@ -442,6 +442,14 @@ def test_wrong_event_type(self): ) self.assertEqual(e.line, 2) + def test_nameless_event(self): + with self.assertRaises(ValidationError) as ex: + self.open_yaml("yaml/errors/events/nameless_event.yaml") + e = ex.exception + msg = e.message.lower() + self.assertIn("at least one of name or prefix", msg) + self.assertEqual(e.line, 2) + def open_yaml(self, path): with open(self.load_file(path), encoding="utf-8") as file: return parse_semantic_convention_groups(file) diff --git a/semantic-conventions/src/tests/semconv/templating/test_markdown.py b/semantic-conventions/src/tests/semconv/templating/test_markdown.py index 3ee8f21d..21aebacf 100644 --- a/semantic-conventions/src/tests/semconv/templating/test_markdown.py +++ b/semantic-conventions/src/tests/semconv/templating/test_markdown.py @@ -117,6 +117,9 @@ def test_units(self): def test_event(self): self.check("markdown/event/") + def test_event_noprefix(self): + self.check("markdown/event_noprefix/") + def check( self, input_dir: str, diff --git a/semantic-conventions/syntax.md b/semantic-conventions/syntax.md index aa2a7699..f5b8426f 100644 --- a/semantic-conventions/syntax.md +++ b/semantic-conventions/syntax.md @@ -7,17 +7,21 @@ Then, the semantic of each field is described. -- [JSON Schema](#json-schema) -- [Syntax](#syntax) -- [Semantics](#semantics) - * [Groups](#groups) - * [Semantic Convention](#semantic-convention) - * [Attributes](#attributes) - * [Ref](#ref) - * [Type](#type) - * [Constraints](#constraints) - + [Any Of](#any-of) - + [Include](#include) +- [Semantic Convention YAML Language](#semantic-convention-yaml-language) + - [JSON Schema](#json-schema) + - [Syntax](#syntax) + - [Semantics](#semantics) + - [Groups](#groups) + - [Semantic Convention](#semantic-convention) + - [Span semantic convention](#span-semantic-convention) + - [Event semantic convention](#event-semantic-convention) + - [Attributes](#attributes) + - [Examples (for examples)](#examples-for-examples) + - [Ref](#ref) + - [Type](#type) + - [Constraints](#constraints) + - [Any Of](#any-of) + - [Include](#include) @@ -36,14 +40,14 @@ All attributes are lower case. groups ::= semconv | semconv groups -semconv ::= id [type] brief [note] [prefix] [events] [extends] [stability] [deprecated] [span_kind] attributes [constraints] +semconv ::= id [convtype] brief [note] [prefix] [extends] [stability] [deprecated] attributes [constraints] [specificfields] id ::= string -type ::= "span" # Default if not specified - | "resource" - | "event" - | "metric" +convtype ::= "span" # Default if not specified + | "resource" # see spanspecificfields + | "event" # see eventspecificfields + | "metric" # (currently non-functional) brief ::= string note ::= string @@ -58,13 +62,6 @@ stability ::= "deprecated" deprecated ::= -span_kind ::= "client" - | "server" - | "producer" - | "consumer" - | "internal" - - attributes ::= (id type brief examples | ref [brief] [examples]) [tag] [stability] [deprecated] [required] [sampling_relevant] [note] # ref MUST point to an existing attribute id @@ -106,6 +103,22 @@ any_of ::= id {id} include ::= id +specificfields ::= spanfields + | eventfields + +spanfields ::= [events] [span_kind] +eventfields ::= [name] + +span_kind ::= "client" + | "server" + | "producer" + | "consumer" + | "internal" + +events ::= id {id} # MUST point to an existing event group + +name ::= string + ``` ## Semantics @@ -145,6 +158,14 @@ The following is only valid if `type` is `span` (the default): - `events`, optional list of strings that specify the ids of event semantic conventions associated with this span semantic convention. +#### Event semantic convention + +The following is only valid if `type` is `event`: + +- `name`, conditionally required string. The name of the event. + If not specified, the `prefix` is used. If `prefix` is empty (or unspecified), + `name` is required. + ### Attributes An attribute is defined by: From afb6ea8c99b9ad597a778deb54c0542d7b83d099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Neum=C3=BCller?= Date: Wed, 15 Sep 2021 17:27:55 +0200 Subject: [PATCH 3/5] Add CHANGELOG, bump version. --- semantic-conventions/CHANGELOG.md | 5 +++++ semantic-conventions/src/opentelemetry/semconv/version.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/semantic-conventions/CHANGELOG.md b/semantic-conventions/CHANGELOG.md index 7fc67916..eb40293d 100644 --- a/semantic-conventions/CHANGELOG.md +++ b/semantic-conventions/CHANGELOG.md @@ -2,6 +2,11 @@ Please update the changelog as part of any significant pull request. +## v0.7.0 + +- Add `name` field for events. It defaults to the `prefix` + ([#67](https://github.com/open-telemetry/build-tools/pull/67)). + ## v0.6.0 - Enforce enum member IDs follow the same rules as other IDs diff --git a/semantic-conventions/src/opentelemetry/semconv/version.py b/semantic-conventions/src/opentelemetry/semconv/version.py index a9eab88f..1db76114 100644 --- a/semantic-conventions/src/opentelemetry/semconv/version.py +++ b/semantic-conventions/src/opentelemetry/semconv/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "0.6.0" +__version__ = "0.7.0" From 9e9b0262e95498ec2d2fe0cada53d089ba23992c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Neum=C3=BCller?= Date: Wed, 15 Sep 2021 17:32:05 +0200 Subject: [PATCH 4/5] Add test for event with both prefix and name. --- .../src/tests/data/markdown/event_renamed/event.yaml | 10 ++++++++++ .../src/tests/data/markdown/event_renamed/expected.md | 9 +++++++++ .../src/tests/data/markdown/event_renamed/input.md | 5 +++++ .../src/tests/semconv/templating/test_markdown.py | 3 +++ 4 files changed, 27 insertions(+) create mode 100644 semantic-conventions/src/tests/data/markdown/event_renamed/event.yaml create mode 100644 semantic-conventions/src/tests/data/markdown/event_renamed/expected.md create mode 100644 semantic-conventions/src/tests/data/markdown/event_renamed/input.md diff --git a/semantic-conventions/src/tests/data/markdown/event_renamed/event.yaml b/semantic-conventions/src/tests/data/markdown/event_renamed/event.yaml new file mode 100644 index 00000000..f90d2e53 --- /dev/null +++ b/semantic-conventions/src/tests/data/markdown/event_renamed/event.yaml @@ -0,0 +1,10 @@ +groups: + - id: event + name: myname + prefix: myprefix + type: event + brief: brief + attributes: + - id: attr + type: boolean + brief: attrbrief diff --git a/semantic-conventions/src/tests/data/markdown/event_renamed/expected.md b/semantic-conventions/src/tests/data/markdown/event_renamed/expected.md new file mode 100644 index 00000000..0c910126 --- /dev/null +++ b/semantic-conventions/src/tests/data/markdown/event_renamed/expected.md @@ -0,0 +1,9 @@ +# Test + + +The event name MUST be `myname`. + +| Attribute | Type | Description | Examples | Required | +|---|---|---|---|---| +| `myprefix.attr` | boolean | attrbrief | | No | + diff --git a/semantic-conventions/src/tests/data/markdown/event_renamed/input.md b/semantic-conventions/src/tests/data/markdown/event_renamed/input.md new file mode 100644 index 00000000..69adbf92 --- /dev/null +++ b/semantic-conventions/src/tests/data/markdown/event_renamed/input.md @@ -0,0 +1,5 @@ +# Test + + + + diff --git a/semantic-conventions/src/tests/semconv/templating/test_markdown.py b/semantic-conventions/src/tests/semconv/templating/test_markdown.py index 21aebacf..f0602d6c 100644 --- a/semantic-conventions/src/tests/semconv/templating/test_markdown.py +++ b/semantic-conventions/src/tests/semconv/templating/test_markdown.py @@ -120,6 +120,9 @@ def test_event(self): def test_event_noprefix(self): self.check("markdown/event_noprefix/") + def test_event_renamed(self): + self.check("markdown/event_renamed/") + def check( self, input_dir: str, From 43d5d4bd8acb0455eac4d5ab1567023fe56485ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Neum=C3=BCller?= Date: Thu, 23 Sep 2021 10:54:27 +0200 Subject: [PATCH 5/5] Bump version.py. --- semantic-conventions/src/opentelemetry/semconv/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/semantic-conventions/src/opentelemetry/semconv/version.py b/semantic-conventions/src/opentelemetry/semconv/version.py index 1db76114..68687d3e 100644 --- a/semantic-conventions/src/opentelemetry/semconv/version.py +++ b/semantic-conventions/src/opentelemetry/semconv/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "0.7.0" +__version__ = "0.8.0"