diff --git a/semantic-conventions/CHANGELOG.md b/semantic-conventions/CHANGELOG.md index ef78e9cb..26be0a24 100644 --- a/semantic-conventions/CHANGELOG.md +++ b/semantic-conventions/CHANGELOG.md @@ -6,6 +6,8 @@ Please update the changelog as part of any significant pull request. - When an attribute is referenced using `ref:` from a group that already inherits the attribute with `extends:`, resolve the reference to the closest inherited attribute instead of the primary definition. This makes a difference in case the inherited reference overwrites any properties. ([#204](https://github.com/open-telemetry/build-tools/pull/204)) +- Sort attributes by name + ([#205](https://github.com/open-telemetry/build-tools/pull/205)) ## v0.21.0 diff --git a/semantic-conventions/src/opentelemetry/semconv/model/semantic_convention.py b/semantic-conventions/src/opentelemetry/semconv/model/semantic_convention.py index 6f91ae2e..0056d1e6 100644 --- a/semantic-conventions/src/opentelemetry/semconv/model/semantic_convention.py +++ b/semantic-conventions/src/opentelemetry/semconv/model/semantic_convention.py @@ -126,12 +126,15 @@ def _get_attributes(self, templates: Optional[bool]): if not hasattr(self, "attrs_by_name"): return [] - return [ - attr - for attr in self.attrs_by_name.values() - if templates is None - or templates == AttributeType.is_template_type(attr.attr_type) - ] + return sorted( + [ + attr + for attr in self.attrs_by_name.values() + if templates is None + or templates == AttributeType.is_template_type(attr.attr_type) + ], + key=lambda attr: attr.fqn, + ) def __init__(self, group): super().__init__(group) @@ -431,32 +434,13 @@ def _populate_extends_single(self, semconv, unprocessed): parent_attributes = {} for ext_attr in extended.attributes: parent_attributes[ext_attr.fqn] = ext_attr.inherit_attribute() - # By induction, parent semconv is already correctly sorted - parent_attributes.update( - SemanticConventionSet._sort_attributes_dict(semconv.attrs_by_name) - ) - if parent_attributes or semconv.attributes: - semconv.attrs_by_name = parent_attributes - elif semconv.attributes: # No parent, sort of current attributes - semconv.attrs_by_name = SemanticConventionSet._sort_attributes_dict( - semconv.attrs_by_name - ) + + parent_attributes.update(semconv.attrs_by_name) + semconv.attrs_by_name = parent_attributes + # delete from remaining semantic conventions to process del unprocessed[semconv.semconv_id] - @staticmethod - def _sort_attributes_dict( - attributes: typing.Dict[str, SemanticAttribute] - ) -> typing.Dict[str, SemanticAttribute]: - """ - First imported, and then defined attributes. - :param attributes: Dictionary of attributes to sort - :return: A sorted dictionary of attributes - """ - return dict( - sorted(attributes.items(), key=lambda kv: 0 if kv[1].imported else 1) - ) - def _populate_anyof_attributes(self): any_of: AnyOf for semconv in self.models.values(): diff --git a/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py b/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py index 630e3c80..9871662e 100644 --- a/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py +++ b/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py @@ -207,10 +207,7 @@ def to_markdown_attribute_table( self, semconv: BaseSemanticConvention, output: io.StringIO ): attr_to_print = [] - for attr in sorted( - semconv.attributes_and_templates, - key=lambda a: "" if a.ref is None else a.ref, - ): + for attr in semconv.attributes_and_templates: if self.render_ctx.group_key is not None: if attr.tag == self.render_ctx.group_key: attr_to_print.append(attr) diff --git a/semantic-conventions/src/tests/data/markdown/deprecated/expected.md b/semantic-conventions/src/tests/data/markdown/deprecated/expected.md index d35ec246..988ac7c8 100644 --- a/semantic-conventions/src/tests/data/markdown/deprecated/expected.md +++ b/semantic-conventions/src/tests/data/markdown/deprecated/expected.md @@ -4,14 +4,14 @@ | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| -| `http.method` | string | HTTP request method. | `GET`; `POST`; `HEAD` | Required | -| `http.url` | string | Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]`. Usually the fragment is not transmitted over HTTP, but if it is known, it should be included nevertheless. | `https://www.foo.bar/search?q=OpenTelemetry#SemConv` | Recommended | -| `http.target` | string | The full request target as passed in a HTTP request line or equivalent. | `/path/12314/?q=ddds#123` | Recommended | +| `http.flavor` | string | **Deprecated. Use attribute `flavor_new` instead.**
Kind of HTTP protocol used [1] | `1.0` | Recommended | | `http.host` | string | The value of the [HTTP host header](https://tools.ietf.org/html/rfc7230#section-5.4). When the header is empty or not present, this attribute should be the same. | `www.example.org` | Recommended | +| `http.method` | string | HTTP request method. | `GET`; `POST`; `HEAD` | Required | | `http.scheme` | string | The URI scheme identifying the used protocol. | `http`; `https` | Recommended | | `http.status_code` | int | [HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6). | `200` | Conditionally Required: if and only if one was received/sent | | `http.status_text` | string | **Deprecated: Use attribute `status_description` instead.**
[HTTP reason phrase](https://tools.ietf.org/html/rfc7230#section-3.1.2). | `OK` | Recommended | -| `http.flavor` | string | **Deprecated. Use attribute `flavor_new` instead.**
Kind of HTTP protocol used [1] | `1.0` | Recommended | +| `http.target` | string | The full request target as passed in a HTTP request line or equivalent. | `/path/12314/?q=ddds#123` | Recommended | +| `http.url` | string | Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]`. Usually the fragment is not transmitted over HTTP, but if it is known, it should be included nevertheless. | `https://www.foo.bar/search?q=OpenTelemetry#SemConv` | Recommended | | `http.user_agent` | string | Value of the [HTTP User-Agent](https://tools.ietf.org/html/rfc7231#section-5.5.3) header sent by the client. | `CERN-LineMode/2.15 libwww/2.17b3` | Recommended | **[1]:** If `net.transport` is not specified, it can be assumed to be `IP.TCP` except if `http.flavor` is `QUIC`, in which case `IP.UDP` is assumed. diff --git a/semantic-conventions/src/tests/data/markdown/event/expected.md b/semantic-conventions/src/tests/data/markdown/event/expected.md index f69ad312..41274345 100644 --- a/semantic-conventions/src/tests/data/markdown/event/expected.md +++ b/semantic-conventions/src/tests/data/markdown/event/expected.md @@ -5,10 +5,10 @@ The event name MUST be `exception`. | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| -| `exception.type` | string | The type of the exception. | `java.net.ConnectException`; `OSError` | See below | +| `exception.escaped` | boolean | SHOULD be set to true if the exception event is recorded at a point where it is known that the exception is escaping the scope of the span. [1] | | Recommended | | `exception.message` | string | The exception message. | `Division by zero`; `Can't convert 'int' object to str implicitly` | See below | | `exception.stacktrace` | string | A stacktrace. | `Exception in thread "main" java.lang.RuntimeException: Test exception\n at com.example.GenerateTrace.methodB(GenerateTrace.java:13)\n at com.example.GenerateTrace.methodA(GenerateTrace.java:9)\n at com.example.GenerateTrace.main(GenerateTrace.java:5)` | Recommended | -| `exception.escaped` | boolean | SHOULD be set to true if the exception event is recorded at a point where it is known that the exception is escaping the scope of the span. [1] | | Recommended | +| `exception.type` | string | The type of the exception. | `java.net.ConnectException`; `OSError` | See below | **[1]:** An exception is considered to have escaped. diff --git a/semantic-conventions/src/tests/data/markdown/extend_constraint/expected.md b/semantic-conventions/src/tests/data/markdown/extend_constraint/expected.md index 6a13b2aa..66372a62 100644 --- a/semantic-conventions/src/tests/data/markdown/extend_constraint/expected.md +++ b/semantic-conventions/src/tests/data/markdown/extend_constraint/expected.md @@ -36,8 +36,8 @@ Some database systems may allow a connection to switch to a different `db.user`, | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| -| `db.system` | string | An identifier for the database management system (DBMS) product being used. See below for a list of well-known identifiers. | `other_sql` | Required | | `db.connection_string` | string | The connection string used to connect to the database. [1] | `Server=(localdb)\v11.0;Integrated Security=true;` | Recommended | +| `db.system` | string | An identifier for the database management system (DBMS) product being used. See below for a list of well-known identifiers. | `other_sql` | Required | | `db.user` | string | Username for accessing the database. | `readonly_user`; `reporting_user` | Recommended | | `net.peer.ip` | string | Remote address of the peer (dotted decimal for IPv4 or [RFC5952](https://tools.ietf.org/html/rfc5952) for IPv6) | `127.0.0.1` | See below | | `net.peer.name` | string | Remote hostname or similar, see note below. | `example.com` | See below | @@ -127,8 +127,8 @@ When additional attributes are added that only apply to a specific DBMS, its ide | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| -| `db.mssql.instance_name` | string | The Microsoft SQL Server [instance name](https://docs.microsoft.com/en-us/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15) connecting to. This name is used to determine the port of a named instance. [1] | `MSSQLSERVER` | Recommended | | `db.jdbc.driver_classname` | string | The fully-qualified class name of the JDBC driver used to connect. | `org.postgresql.Driver`; `com.microsoft.sqlserver.jdbc.SQLServerDriver` | Recommended | +| `db.mssql.instance_name` | string | The Microsoft SQL Server [instance name](https://docs.microsoft.com/en-us/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15) connecting to. This name is used to determine the port of a named instance. [1] | `MSSQLSERVER` | Recommended | **[1]:** If setting a `db.mssql.instance_name`, `net.peer.port` is no longer required (but still recommended if non-standard). @@ -142,16 +142,16 @@ Usually only one `db.name` will be used per connection though. | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| | `db.name` | string | If no tech-specific attribute is defined, this attribute is used to report the name of the database being accessed. For commands that switch the database, this should be set to the target database (even if the command fails). [1] | `customers`; `main` | Conditionally Required: [2] | -| `db.statement` | string | The database statement being executed. [3] | `SELECT * FROM wuser_table`; `SET mykey "WuValue"` | Conditionally Required: if applicable. | -| `db.operation` | string | The name of the operation being executed, e.g. the [MongoDB command name](https://docs.mongodb.com/manual/reference/command/#database-operations) such as `findAndModify`. [4] | `findAndModify`; `HMSET` | Conditionally Required: if `db.statement` is not applicable. | +| `db.operation` | string | The name of the operation being executed, e.g. the [MongoDB command name](https://docs.mongodb.com/manual/reference/command/#database-operations) such as `findAndModify`. [3] | `findAndModify`; `HMSET` | Conditionally Required: if `db.statement` is not applicable. | +| `db.statement` | string | The database statement being executed. [4] | `SELECT * FROM wuser_table`; `SET mykey "WuValue"` | Conditionally Required: if applicable. | **[1]:** In some SQL databases, the database name to be used is called "schema name". **[2]:** if applicable and no more-specific attribute is defined. -**[3]:** The value may be sanitized to exclude sensitive information. +**[3]:** While it would semantically make sense to set this, e.g., to a SQL keyword like `SELECT` or `INSERT`, it is not recommended to attempt any client-side parsing of `db.statement` just to get this property (the back end can do that if required). -**[4]:** While it would semantically make sense to set this, e.g., to a SQL keyword like `SELECT` or `INSERT`, it is not recommended to attempt any client-side parsing of `db.statement` just to get this property (the back end can do that if required). +**[4]:** The value may be sanitized to exclude sensitive information. For **Redis**, the value provided for `db.statement` SHOULD correspond to the syntax of the Redis CLI. diff --git a/semantic-conventions/src/tests/data/markdown/extend_grandparent/database.yaml b/semantic-conventions/src/tests/data/markdown/extend_grandparent/database.yaml new file mode 100644 index 00000000..af4aaa1d --- /dev/null +++ b/semantic-conventions/src/tests/data/markdown/extend_grandparent/database.yaml @@ -0,0 +1,35 @@ +groups: + - id: database.common_attributes + prefix: db + type: attribute_group + brief: These attributes describe database calls. + attributes: + - id: name + brief: Database name. + type: string + examples: [ 'the_shop' ] + + - id: database.foo.attributes + prefix: db.foo + type: attribute_group + brief: These attributes describe database Foo calls. + extends: database.common_attributes + attributes: + - id: bar + brief: Some property. + type: string + examples: [ 'baz' ] + + - id: database.foo.span + prefix: db.foo + type: span + brief: These attributes describe database Foo spans. + extends: database.foo.attributes + + - id: database.foo.duration.metric + type: metric + metric_name: db.foo.duration + instrument: histogram + unit: s + brief: Measures the duration of database Foo calls. + extends: database.foo.attributes diff --git a/semantic-conventions/src/tests/data/markdown/extend_grandparent/expected.md b/semantic-conventions/src/tests/data/markdown/extend_grandparent/expected.md new file mode 100644 index 00000000..3964e411 --- /dev/null +++ b/semantic-conventions/src/tests/data/markdown/extend_grandparent/expected.md @@ -0,0 +1,23 @@ +## DB spans + + +| Attribute | Type | Description | Examples | Requirement Level | +|---|---|---|---|---| +| `db.foo.bar` | string | Some property. | `baz` | Recommended | +| `db.name` | string | Database name. | `the_shop` | Recommended | + + +## DB metrics + + +| Name | Instrument Type | Unit (UCUM) | Description | +| -------- | --------------- | ----------- | -------------- | +| `db.foo.duration` | Histogram | `s` | Measures the duration of database Foo calls. | + + + +| Attribute | Type | Description | Examples | Requirement Level | +|---|---|---|---|---| +| `db.foo.bar` | string | Some property. | `baz` | Recommended | +| `db.name` | string | Database name. | `the_shop` | Recommended | + diff --git a/semantic-conventions/src/tests/data/markdown/extend_grandparent/input.md b/semantic-conventions/src/tests/data/markdown/extend_grandparent/input.md new file mode 100644 index 00000000..9ed9edff --- /dev/null +++ b/semantic-conventions/src/tests/data/markdown/extend_grandparent/input.md @@ -0,0 +1,12 @@ +## DB spans + + + + +## DB metrics + + + + + + diff --git a/semantic-conventions/src/tests/data/markdown/include/expected.md b/semantic-conventions/src/tests/data/markdown/include/expected.md index 1a093a7c..d29c6fff 100644 --- a/semantic-conventions/src/tests/data/markdown/include/expected.md +++ b/semantic-conventions/src/tests/data/markdown/include/expected.md @@ -3,19 +3,19 @@ | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| -| `faas.trigger` | string | Type of the trigger on which the function is executed. | `datasource` | Required | | `faas.execution` | string | The execution id of the current function execution. | `af9d5aa4-a685-4c5f-a22b-444f80b3cc28` | Recommended | -| `http.method` | string | HTTP request method. | `GET`; `POST`; `HEAD` | Required | -| `http.url` | string | Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]`. Usually the fragment is not transmitted over HTTP, but if it is known, it should be included nevertheless. | `https://www.foo.bar/search?q=OpenTelemetry#SemConv` | See below | -| `http.target` | string | The full request target as passed in a HTTP request line or equivalent. | `/path/12314/?q=ddds#123` | See below | +| `faas.trigger` | string | Type of the trigger on which the function is executed. | `datasource` | Required | | `http.host` | string | The value of the [HTTP host header](https://tools.ietf.org/html/rfc7230#section-5.4). When the header is empty or not present, this attribute should be the same. | `www.example.org` | See below | +| `http.method` | string | HTTP request method. | `GET`; `POST`; `HEAD` | Required | +| `http.recommended_attribute` | string | brief | `foo` | Recommended: short note | +| `http.recommended_attribute_long_note` | string | brief | `bar` | Recommended: [1] | | `http.scheme` | string | The URI scheme identifying the used protocol. | `http`; `https` | See below | +| [`http.server_name`](input_http.md) | string | The primary server name of the matched virtual host. [2] | `example.com` | Conditionally Required: [3] | | `http.status_code` | int | [HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6). | `200` | Conditionally Required: if and only if one was received/sent | | `http.status_text` | string | [HTTP reason phrase](https://tools.ietf.org/html/rfc7230#section-3.1.2). | `OK` | Recommended | +| `http.target` | string | The full request target as passed in a HTTP request line or equivalent. | `/path/12314/?q=ddds#123` | See below | +| `http.url` | string | Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]`. Usually the fragment is not transmitted over HTTP, but if it is known, it should be included nevertheless. | `https://www.foo.bar/search?q=OpenTelemetry#SemConv` | See below | | `http.user_agent` | string | Value of the [HTTP User-Agent](https://tools.ietf.org/html/rfc7231#section-5.5.3) header sent by the client. | `CERN-LineMode/2.15 libwww/2.17b3` | Recommended | -| `http.recommended_attribute` | string | brief | `foo` | Recommended: short note | -| `http.recommended_attribute_long_note` | string | brief | `bar` | Recommended: [1] | -| [`http.server_name`](input_http.md) | string | The primary server name of the matched virtual host. [2] | `example.com` | Conditionally Required: [3] | **[1]:** some very long note that should be written under the semconv table diff --git a/semantic-conventions/src/tests/data/markdown/multiple/expected.md b/semantic-conventions/src/tests/data/markdown/multiple/expected.md index f33a75a1..24b84332 100644 --- a/semantic-conventions/src/tests/data/markdown/multiple/expected.md +++ b/semantic-conventions/src/tests/data/markdown/multiple/expected.md @@ -4,26 +4,26 @@ | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| -| `http.method` | string | HTTP request method. | `GET`; `POST`; `HEAD` | Required | -| `http.url` | string | Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]`. Usually the fragment is not transmitted over HTTP, but if it is known, it should be included nevertheless. | `https://www.foo.bar/search?q=OpenTelemetry#SemConv` | Recommended | -| `http.target` | string | The full request target as passed in a HTTP request line or equivalent. | `/path/12314/?q=ddds#123` | Recommended | | `http.host` | string | The value of the [HTTP host header](https://tools.ietf.org/html/rfc7230#section-5.4). When the header is empty or not present, this attribute should be the same. | `www.example.org` | Recommended | +| `http.method` | string | HTTP request method. | `GET`; `POST`; `HEAD` | Required | | `http.scheme` | string | The URI scheme identifying the used protocol. | `http`; `https` | Recommended | | `http.status_code` | int | [HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6). | `200` | Conditionally Required: if and only if one was received/sent | | `http.status_text` | string | [HTTP reason phrase](https://tools.ietf.org/html/rfc7230#section-3.1.2). | `OK` | Recommended | +| `http.target` | string | The full request target as passed in a HTTP request line or equivalent. | `/path/12314/?q=ddds#123` | Recommended | +| `http.url` | string | Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]`. Usually the fragment is not transmitted over HTTP, but if it is known, it should be included nevertheless. | `https://www.foo.bar/search?q=OpenTelemetry#SemConv` | Recommended | | `http.user_agent` | string | Value of the [HTTP User-Agent](https://tools.ietf.org/html/rfc7231#section-5.5.3) header sent by the client. | `CERN-LineMode/2.15 libwww/2.17b3` | Recommended | | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| -| `http.method` | string | HTTP request method. | `GET`; `POST`; `HEAD` | Required | -| `http.url` | string | Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]`. Usually the fragment is not transmitted over HTTP, but if it is known, it should be included nevertheless. | `https://www.foo.bar/search?q=OpenTelemetry#SemConv` | Recommended | -| `http.target` | string | The full request target as passed in a HTTP request line or equivalent. | `/path/12314/?q=ddds#123` | Recommended | | `http.host` | string | The value of the [HTTP host header](https://tools.ietf.org/html/rfc7230#section-5.4). When the header is empty or not present, this attribute should be the same. | `www.example.org` | Recommended | +| `http.method` | string | HTTP request method. | `GET`; `POST`; `HEAD` | Required | | `http.scheme` | string | The URI scheme identifying the used protocol. | `http`; `https` | Recommended | | `http.status_code` | int | [HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6). | `200` | Conditionally Required: if and only if one was received/sent | | `http.status_text` | string | [HTTP reason phrase](https://tools.ietf.org/html/rfc7230#section-3.1.2). | `OK` | Recommended | +| `http.target` | string | The full request target as passed in a HTTP request line or equivalent. | `/path/12314/?q=ddds#123` | Recommended | +| `http.url` | string | Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]`. Usually the fragment is not transmitted over HTTP, but if it is known, it should be included nevertheless. | `https://www.foo.bar/search?q=OpenTelemetry#SemConv` | Recommended | | `http.user_agent` | string | Value of the [HTTP User-Agent](https://tools.ietf.org/html/rfc7231#section-5.5.3) header sent by the client. | `CERN-LineMode/2.15 libwww/2.17b3` | Recommended | diff --git a/semantic-conventions/src/tests/data/markdown/multiple_enum/expected.md b/semantic-conventions/src/tests/data/markdown/multiple_enum/expected.md index 11076aa9..96781fc4 100644 --- a/semantic-conventions/src/tests/data/markdown/multiple_enum/expected.md +++ b/semantic-conventions/src/tests/data/markdown/multiple_enum/expected.md @@ -4,33 +4,26 @@ | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| -| `net.transport` | string | Transport protocol used. See note below. | `IP.TCP` | Recommended | -| `net.host.connection.type` | string | unavailable | `wifi` | Recommended | -| `net.host.connection.subtype` | string | This describes more details regarding the connection.type. It may be the type of cell connection, but it could be used for describing details about a wifi connection. | `2G` | Recommended | -| `net.host.carrier.name` | string | host.carrier.name | `sprint` | Recommended | +| `net.host.carrier.icc` | string | host.carrier.icc | `DE` | Recommended | | `net.host.carrier.mcc` | string | host.carrier.mcc | `310` | Recommended | | `net.host.carrier.mnc` | string | host.carrier.mnc | `001` | Recommended | -| `net.host.carrier.icc` | string | host.carrier.icc | `DE` | Recommended | -| `net.peer.ip` | string | Remote address of the peer (dotted decimal for IPv4 or [RFC5952](https://tools.ietf.org/html/rfc5952) for IPv6) | `127.0.0.1` | Recommended | -| `net.peer.port` | int | Remote port number. | `80`; `8080`; `443` | Recommended | -| `net.peer.name` | string | Remote hostname or similar, see note below. | `example.com` | Recommended | +| `net.host.carrier.name` | string | host.carrier.name | `sprint` | Recommended | +| `net.host.connection.subtype` | string | This describes more details regarding the connection.type. It may be the type of cell connection, but it could be used for describing details about a wifi connection. | `2G` | Recommended | +| `net.host.connection.type` | string | unavailable | `wifi` | Recommended | | `net.host.ip` | string | Like `net.peer.ip` but for the host IP. Useful in case of a multi-IP host. | `192.168.0.1` | Recommended | -| `net.host.port` | int | Like `net.peer.port` but for the host port. | `35555` | Recommended | | `net.host.name` | string | Local hostname or similar, see note below. | `localhost` | Recommended | +| `net.host.port` | int | Like `net.peer.port` but for the host port. | `35555` | Recommended | +| `net.peer.ip` | string | Remote address of the peer (dotted decimal for IPv4 or [RFC5952](https://tools.ietf.org/html/rfc5952) for IPv6) | `127.0.0.1` | Recommended | +| `net.peer.name` | string | Remote hostname or similar, see note below. | `example.com` | Recommended | +| `net.peer.port` | int | Remote port number. | `80`; `8080`; `443` | Recommended | +| `net.transport` | string | Transport protocol used. See note below. | `IP.TCP` | Recommended | -`net.transport` MUST be one of the following: +`net.host.connection.subtype` has the following list of well-known values. If one of them applies, then the respective value MUST be used, otherwise a custom value MAY be used. | Value | Description | |---|---| -| `IP.TCP` | ip.tcp | -| `IP.UDP` | ip.udp | -| `IP` | Another IP-based protocol | -| `Unix` | Unix Domain socket. See below. | -| `pipe` | Named or anonymous pipe. See note below. | -| `inproc` | In-process communication. [1] | -| `other` | Something else (non IP-based). | - -**[1]:** Signals that there is only in-process communication not using a "real" network protocol in cases where network attributes would normally be expected. Usually all other network attributes can be left out in that case. +| `1G` | 1G | +| `2G` | 2G | `net.host.connection.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used, otherwise a custom value MAY be used. @@ -43,10 +36,17 @@ **[1]:** Usually 802.11 -`net.host.connection.subtype` has the following list of well-known values. If one of them applies, then the respective value MUST be used, otherwise a custom value MAY be used. +`net.transport` MUST be one of the following: | Value | Description | |---|---| -| `1G` | 1G | -| `2G` | 2G | +| `IP.TCP` | ip.tcp | +| `IP.UDP` | ip.udp | +| `IP` | Another IP-based protocol | +| `Unix` | Unix Domain socket. See below. | +| `pipe` | Named or anonymous pipe. See note below. | +| `inproc` | In-process communication. [1] | +| `other` | Something else (non IP-based). | + +**[1]:** Signals that there is only in-process communication not using a "real" network protocol in cases where network attributes would normally be expected. Usually all other network attributes can be left out in that case. diff --git a/semantic-conventions/src/tests/data/markdown/omit_requirement_level/expected.md b/semantic-conventions/src/tests/data/markdown/omit_requirement_level/expected.md index 501567bc..ffa730ac 100644 --- a/semantic-conventions/src/tests/data/markdown/omit_requirement_level/expected.md +++ b/semantic-conventions/src/tests/data/markdown/omit_requirement_level/expected.md @@ -4,6 +4,6 @@ | Attribute | Type | Description | Examples | |---|---|---|---| | `http.method` | string | HTTP request method. | `GET`; `POST`; `HEAD` | -| `http.url` | string | Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]`. Usually the fragment is not transmitted over HTTP, but if it is known, it should be included nevertheless. | `https://www.foo.bar/search?q=OpenTelemetry#SemConv` | | `http.target` | string | The full request target as passed in a HTTP request line or equivalent. | `/path/12314/?q=ddds#123` | +| `http.url` | string | Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]`. Usually the fragment is not transmitted over HTTP, but if it is known, it should be included nevertheless. | `https://www.foo.bar/search?q=OpenTelemetry#SemConv` | diff --git a/semantic-conventions/src/tests/data/markdown/parameter_full/expected.md b/semantic-conventions/src/tests/data/markdown/parameter_full/expected.md index 75e6d134..1ff9a1c2 100644 --- a/semantic-conventions/src/tests/data/markdown/parameter_full/expected.md +++ b/semantic-conventions/src/tests/data/markdown/parameter_full/expected.md @@ -3,25 +3,25 @@ | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| -| `faas.trigger` | string | Type of the trigger on which the function is executed. | `datasource` | Required | | `faas.execution` | string | The execution id of the current function execution. | `af9d5aa4-a685-4c5f-a22b-444f80b3cc28` | Recommended | -| `http.method` | string | HTTP request method. | `GET`; `POST`; `HEAD` | Required | -| `http.url` | string | Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]`. Usually the fragment is not transmitted over HTTP, but if it is known, it should be included nevertheless. | `https://www.foo.bar/search?q=OpenTelemetry#SemConv` | See below | -| `http.target` | string | The full request target as passed in a HTTP request line or equivalent. | `/path/12314/?q=ddds#123` | See below | +| `faas.trigger` | string | Type of the trigger on which the function is executed. | `datasource` | Required | +| [`http.client_ip`](http.md) | string | The IP address of the original client behind all proxies, if known (e.g. from [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For)). [1] | `83.164.160.102` | Recommended | | `http.host` | string | The value of the [HTTP host header](https://tools.ietf.org/html/rfc7230#section-5.4). When the header is empty or not present, this attribute should be the same. | `www.example.org` | Conditionally Required: | +| `http.method` | string | HTTP request method. | `GET`; `POST`; `HEAD` | Required | +| [`http.route`](http.md) | string | The matched route (path template). | `/users/:userID?` | Recommended | | `http.scheme` | string | The URI scheme identifying the used protocol. | `http`; `https` | See below | +| [`http.server_name`](http.md) | string | The primary server name of the matched virtual host. [2] | `example.com` | Conditionally Required: [3] | | `http.status_code` | int | [HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6). | `200` | Conditionally Required: if and only if one was received/sent. | | `http.status_text` | string | [HTTP reason phrase](https://tools.ietf.org/html/rfc7230#section-3.1.2). | `OK` | Recommended | +| `http.target` | string | The full request target as passed in a HTTP request line or equivalent. | `/path/12314/?q=ddds#123` | See below | +| `http.url` | string | Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]`. Usually the fragment is not transmitted over HTTP, but if it is known, it should be included nevertheless. | `https://www.foo.bar/search?q=OpenTelemetry#SemConv` | See below | | `http.user_agent` | string | Value of the [HTTP User-Agent](https://tools.ietf.org/html/rfc7231#section-5.5.3) header sent by the client. | `CERN-LineMode/2.15 libwww/2.17b3` | Recommended | -| [`http.server_name`](http.md) | string | The primary server name of the matched virtual host. [1] | `example.com` | Conditionally Required: [2] | -| [`http.route`](http.md) | string | The matched route (path template). | `/users/:userID?` | Recommended | -| [`http.client_ip`](http.md) | string | The IP address of the original client behind all proxies, if known (e.g. from [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For)). [3] | `83.164.160.102` | Recommended | -**[1]:** http.url is usually not readily available on the server side but would have to be assembled in a cumbersome and sometimes lossy process from other information (see e.g. open-telemetry/opentelemetry-python/pull/148). It is thus preferred to supply the raw data that is available. +**[1]:** This is not necessarily the same as `net.peer.ip`, which would identify the network-level peer, which may be a proxy. -**[2]:** This should be obtained via configuration. If this attribute can be obtained, this attribute MUST NOT be set ( `net.host.name` should be used instead). +**[2]:** http.url is usually not readily available on the server side but would have to be assembled in a cumbersome and sometimes lossy process from other information (see e.g. open-telemetry/opentelemetry-python/pull/148). It is thus preferred to supply the raw data that is available. -**[3]:** This is not necessarily the same as `net.peer.ip`, which would identify the network-level peer, which may be a proxy. +**[3]:** This should be obtained via configuration. If this attribute can be obtained, this attribute MUST NOT be set ( `net.host.name` should be used instead). **Additional attribute requirements:** At least one of the following sets of attributes is required: diff --git a/semantic-conventions/src/tests/data/markdown/parameter_remove_constraint/expected.md b/semantic-conventions/src/tests/data/markdown/parameter_remove_constraint/expected.md index d126a6c1..f37e496b 100644 --- a/semantic-conventions/src/tests/data/markdown/parameter_remove_constraint/expected.md +++ b/semantic-conventions/src/tests/data/markdown/parameter_remove_constraint/expected.md @@ -3,8 +3,8 @@ | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| -| `db.type` | string | Database type. For any SQL database, "sql". For others, the lower-case database category. | `sql` | Required | | `db.connection_string` | string | The connection string used to connect to the database. [1] | `Server=(localdb)\v11.0;Integrated Security=true;` | Recommended | +| `db.type` | string | Database type. For any SQL database, "sql". For others, the lower-case database category. | `sql` | Required | | `db.user` | string | Username for accessing the database. | `readonly_user`; `reporting_user` | Recommended | | `net.peer.ip` | string | Remote address of the peer (dotted decimal for IPv4 or [RFC5952](https://tools.ietf.org/html/rfc5952) for IPv6) | `127.0.0.1` | Recommended | | `net.peer.name` | string | Remote hostname or similar, see note below. | `example.com` | Recommended | diff --git a/semantic-conventions/src/tests/data/markdown/parameter_tag/expected.md b/semantic-conventions/src/tests/data/markdown/parameter_tag/expected.md index 08e186a7..9332a6f9 100644 --- a/semantic-conventions/src/tests/data/markdown/parameter_tag/expected.md +++ b/semantic-conventions/src/tests/data/markdown/parameter_tag/expected.md @@ -3,8 +3,8 @@ | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| -| `db.type` | string | Database type. For any SQL database, "sql". For others, the lower-case database category. | `sql` | Required | | `db.connection_string` | string | The connection string used to connect to the database. [1] | `Server=(localdb)\v11.0;Integrated Security=true;` | Recommended | +| `db.type` | string | Database type. For any SQL database, "sql". For others, the lower-case database category. | `sql` | Required | | `db.user` | string | Username for accessing the database. | `readonly_user`; `reporting_user` | Recommended | | `net.peer.ip` | string | Remote address of the peer (dotted decimal for IPv4 or [RFC5952](https://tools.ietf.org/html/rfc5952) for IPv6) | `127.0.0.1` | See below | | `net.peer.name` | string | Remote hostname or similar, see note below. | `example.com` | See below | diff --git a/semantic-conventions/src/tests/data/markdown/parameter_tag_empty/expected.md b/semantic-conventions/src/tests/data/markdown/parameter_tag_empty/expected.md index de32081d..59acab51 100644 --- a/semantic-conventions/src/tests/data/markdown/parameter_tag_empty/expected.md +++ b/semantic-conventions/src/tests/data/markdown/parameter_tag_empty/expected.md @@ -4,11 +4,11 @@ | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| | `db.dbms` | string | An identifier for the DBMS (database management system) product | `mssql` | Conditionally Required: for `db.type="sql"` | -| `db.mssql.instance_name` | string | The Microsoft SQL Server [instance name](https://docs.microsoft.com/en-us/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15) connecting to. This name is used to determine the port of a named instance. [1] | `MSSQLSERVER` | Recommended | | `db.jdbc.driver_classname` | string | The fully-qualified class name of the JDBC driver used to connect. | `org.postgresql.Driver`; `com.microsoft.sqlserver.jdbc.SQLServerDriver` | Recommended | +| `db.mssql.instance_name` | string | The Microsoft SQL Server [instance name](https://docs.microsoft.com/en-us/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15) connecting to. This name is used to determine the port of a named instance. [1] | `MSSQLSERVER` | Recommended | | `db.name` | string | If no tech-specific attribute is defined below, this attribute is used to report the name of the database being accessed. For commands that switch the database, this should be set to the target database (even if the command fails). [2] | `customers`; `master` | Conditionally Required: [3] | -| `db.statement` | string | A database statement for the given database type. [4] | `SELECT * FROM wuser_table`; `SET mykey "WuValue"` | Conditionally Required: if applicable. | | `db.operation` | string | The type of operation that is executed, e.g. the [MongoDB command name](https://docs.mongodb.com/manual/reference/command/#database-operations) such as `findAndModify`. While it would semantically make sense to set this, e.g., to a SQL keyword like `SELECT` or `INSERT`, it is not recommended to attempt any client-side parsing of `db.statement` just to get this property (the back end can do that if required). | `findAndModify` | Conditionally Required: if `db.statement` is not applicable. | +| `db.statement` | string | A database statement for the given database type. [4] | `SELECT * FROM wuser_table`; `SET mykey "WuValue"` | Conditionally Required: if applicable. | **[1]:** If setting a `db.mssql.instance_name`, `net.peer.port` is no longer required (but still recommended if non-standard). diff --git a/semantic-conventions/src/tests/data/markdown/ref/expected.md b/semantic-conventions/src/tests/data/markdown/ref/expected.md index c9f6c901..9f3a16e9 100644 --- a/semantic-conventions/src/tests/data/markdown/ref/expected.md +++ b/semantic-conventions/src/tests/data/markdown/ref/expected.md @@ -3,11 +3,11 @@ | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| -| `rpc.service` | string | The service name, must be equal to the $service part in the span name. | `EchoService` | Required | | [`net.peer.name`](input_general.md) | string | override brief. [1] | `example.com` | Opt-In | | [`net.peer.port`](input_general.md) | int | It describes the server port the client is connecting to | `80`; `8080`; `443` | Required | | [`net.sock.peer.addr`](input_general.md) | string | Remote socket peer address. | `127.0.0.1`; `/tmp/mysql.sock` | Required | | [`net.sock.peer.port`](input_general.md) | int | Remote socket peer port. | `16456` | Conditionally Required: | +| `rpc.service` | string | The service name, must be equal to the $service part in the span name. | `EchoService` | Required | **[1]:** override note. diff --git a/semantic-conventions/src/tests/data/markdown/sampling_relevant/expected.md b/semantic-conventions/src/tests/data/markdown/sampling_relevant/expected.md index 04c6ecb6..e3cb8b73 100644 --- a/semantic-conventions/src/tests/data/markdown/sampling_relevant/expected.md +++ b/semantic-conventions/src/tests/data/markdown/sampling_relevant/expected.md @@ -3,12 +3,12 @@ | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| -| `http.method` | string | . | `GET` | Required | -| `http.url` | string | . [1] | `.` | Recommended | -| `http.target` | string | . | `.` | Recommended | | `http.host` | string | . | `.` | Recommended | +| `http.method` | string | . | `GET` | Required | | `http.scheme` | string | . | `http` | Recommended | | `http.status_code` | int | . | | Conditionally Required: | +| `http.target` | string | . | `.` | Recommended | +| `http.url` | string | . [1] | `.` | Recommended | | `http.user_agent` | string | . | `.` | Recommended | | [`net.peer.ip`](span-general.md) | string | . | `.` | Recommended | | [`net.peer.name`](span-general.md) | string | . | `.` | Recommended | @@ -18,11 +18,11 @@ Following attributes MUST be provided **at span creation time** (when provided at all), so they can be considered for sampling decisions: -* `http.method` -* `http.url` -* `http.target` * `http.host` +* `http.method` * `http.scheme` +* `http.target` +* `http.url` * [`net.peer.ip`](span-general.md) * [`net.peer.name`](span-general.md) * [`net.peer.port`](span-general.md) diff --git a/semantic-conventions/src/tests/data/markdown/single/expected.md b/semantic-conventions/src/tests/data/markdown/single/expected.md index f60a901a..f10e136d 100644 --- a/semantic-conventions/src/tests/data/markdown/single/expected.md +++ b/semantic-conventions/src/tests/data/markdown/single/expected.md @@ -4,13 +4,13 @@ | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| -| `http.method` | string | HTTP request method. | `GET`; `POST`; `HEAD` | Required | -| `http.url` | string | Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]`. Usually the fragment is not transmitted over HTTP, but if it is known, it should be included nevertheless. | `https://www.foo.bar/search?q=OpenTelemetry#SemConv` | Recommended | -| `http.target` | string | The full request target as passed in a HTTP request line or equivalent. | `/path/12314/?q=ddds#123` | Recommended | | `http.host` | string | The value of the [HTTP host header](https://tools.ietf.org/html/rfc7230#section-5.4). When the header is empty or not present, this attribute should be the same. | `www.example.org` | Conditionally Required: | +| `http.method` | string | HTTP request method. | `GET`; `POST`; `HEAD` | Required | | `http.scheme` | string | The URI scheme identifying the used protocol. | `http`; `https` | Recommended | | `http.status_code` | int | [HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6). | `200` | Conditionally Required: if and only if one was received/sent. | | `http.status_text` | string | [HTTP reason phrase](https://tools.ietf.org/html/rfc7230#section-3.1.2). | `OK` | Recommended | +| `http.target` | string | The full request target as passed in a HTTP request line or equivalent. | `/path/12314/?q=ddds#123` | Recommended | +| `http.url` | string | Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]`. Usually the fragment is not transmitted over HTTP, but if it is known, it should be included nevertheless. | `https://www.foo.bar/search?q=OpenTelemetry#SemConv` | Recommended | | `http.user_agent` | string | Value of the [HTTP User-Agent](https://tools.ietf.org/html/rfc7231#section-5.5.3) header sent by the client. | `CERN-LineMode/2.15 libwww/2.17b3` | Recommended | diff --git a/semantic-conventions/src/tests/data/markdown/sorting/expected.md b/semantic-conventions/src/tests/data/markdown/sorting/expected.md new file mode 100644 index 00000000..f9a8e1f7 --- /dev/null +++ b/semantic-conventions/src/tests/data/markdown/sorting/expected.md @@ -0,0 +1,12 @@ +# Attributes + + +| Attribute | Type | Description | Examples | Requirement Level | +|---|---|---|---|---| +| `aaa.aaa` | string | the 1st attribute | `aaa` | Recommended | +| `mmm.bbb` | string | the 2nd attribute | `bbb` | Recommended | +| `mmm.ccc.` | string | the 3rd attribute | ``mmm.ccc="ccc"`` | Recommended | +| `nnn.nnn` | string | the 4th attribute | `nnn` | Recommended | +| `zzz.xxx` | string | the 5th attribute | `xxx` | Recommended | +| `zzz.yyy` | string | the 6th attribute | `yyy` | Recommended | + diff --git a/semantic-conventions/src/tests/data/markdown/sorting/input.md b/semantic-conventions/src/tests/data/markdown/sorting/input.md new file mode 100644 index 00000000..56cf652b --- /dev/null +++ b/semantic-conventions/src/tests/data/markdown/sorting/input.md @@ -0,0 +1,4 @@ +# Attributes + + + diff --git a/semantic-conventions/src/tests/data/markdown/sorting/input.yaml b/semantic-conventions/src/tests/data/markdown/sorting/input.yaml new file mode 100644 index 00000000..50260364 --- /dev/null +++ b/semantic-conventions/src/tests/data/markdown/sorting/input.yaml @@ -0,0 +1,52 @@ +groups: + - id: zzz + type: attribute_group + prefix: zzz + brief: 'Attributes that appear last.' + attributes: + - id: yyy + type: string + brief: 'the 6th attribute' + examples: 'yyy' + - id: xxx + type: string + brief: 'the 5th attribute' + examples: 'xxx' + + - id: aaa + type: attribute_group + prefix: aaa + brief: 'Attributes that appear first.' + attributes: + - id: aaa + type: string + brief: 'the 1st attribute' + examples: 'aaa' + + - id: nnn + type: attribute_group + prefix: nnn + brief: 'Attributes that appear after `mmm`.' + attributes: + - id: nnn + type: string + brief: 'the 4th attribute' + examples: 'nnn' + + - id: mmm + type: attribute_group + prefix: mmm + brief: 'Attributes that appear in the middle.' + extends: nnn + attributes: + - id: ccc + type: template[string] + brief: the 3rd attribute + examples: '`mmm.ccc="ccc"`' + - id: bbb + type: string + brief: the 2nd attribute + examples: 'bbb' + - ref: zzz.yyy + - ref: zzz.xxx + - ref: aaa.aaa \ No newline at end of file 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 de4b654c..28196f68 100644 --- a/semantic-conventions/src/tests/data/markdown/stability/badges_expected.md +++ b/semantic-conventions/src/tests/data/markdown/stability/badges_expected.md @@ -3,8 +3,8 @@ | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| +| [`test.def_stability`](labels_expected.md) | boolean | | | Required | +| [`test.deprecated_attr`](labels_expected.md) | boolean | | | 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 | -| [`test.deprecated_attr`](labels_expected.md) | boolean | | | Required | -| [`test.def_stability`](labels_expected.md) | boolean | | | 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 a2298c7a..2ae182e2 100644 --- a/semantic-conventions/src/tests/data/markdown/stability/labels_expected.md +++ b/semantic-conventions/src/tests/data/markdown/stability/labels_expected.md @@ -3,8 +3,8 @@ | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| +| [`test.def_stability`](labels_expected.md) | boolean | | | Required | +| [`test.deprecated_attr`](labels_expected.md) | boolean | | | Required | | [`test.exp_attr`](labels_expected.md) | boolean | | | Required | | [`test.stable_attr`](labels_expected.md) | boolean | | | Required | -| [`test.deprecated_attr`](labels_expected.md) | boolean | | | Required | -| [`test.def_stability`](labels_expected.md) | boolean | | | Required | 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..695ebc54 100644 --- a/semantic-conventions/src/tests/semconv/model/test_correct_parse.py +++ b/semantic-conventions/src/tests/semconv/model/test_correct_parse.py @@ -65,9 +65,9 @@ def test_database(self): "extends": "", "n_constraints": 1, "attributes": [ - "db.type", "db.instance", "db.statement", + "db.type", "db.url", "db.user", ], @@ -84,7 +84,7 @@ def test_faas(self): "prefix": "faas", "extends": "", "n_constraints": 0, - "attributes": ["faas.trigger", "faas.execution"], + "attributes": ["faas.execution", "faas.trigger"], } self.semantic_convention_check(list(semconv.models.values())[0], expected) expected = { @@ -94,9 +94,9 @@ def test_faas(self): "n_constraints": 0, "attributes": [ "faas.document.collection", + "faas.document.name", "faas.document.operation", "faas.document.time", - "faas.document.name", ], } self.semantic_convention_check(list(semconv.models.values())[1], expected) @@ -121,7 +121,7 @@ def test_faas(self): "prefix": "faas", "extends": "faas", "n_constraints": 0, - "attributes": ["faas.time", "faas.cron"], + "attributes": ["faas.cron", "faas.time"], } self.semantic_convention_check(list(semconv.models.values())[4], expected) @@ -136,13 +136,13 @@ def test_general(self): "extends": "", "n_constraints": 0, "attributes": [ - "net.transport", - "net.peer.ip", - "net.peer.port", - "net.peer.name", "net.host.ip", - "net.host.port", "net.host.name", + "net.host.port", + "net.peer.ip", + "net.peer.name", + "net.peer.port", + "net.transport", ], } self.semantic_convention_check(list(semconv.models.values())[0], expected) @@ -166,14 +166,14 @@ def test_http(self): "extends": "", "n_constraints": 0, "attributes": [ - "http.method", - "http.url", - "http.target", + "http.flavor", "http.host", + "http.method", "http.scheme", "http.status_code", "http.status_text", - "http.flavor", + "http.target", + "http.url", "http.user_agent", ], } @@ -244,8 +244,8 @@ def test_resource(self): "extends": "", "n_constraints": 0, "attributes": [ - "cloud.provider", "cloud.account.id", + "cloud.provider", "cloud.region", "cloud.zone", ], @@ -264,10 +264,10 @@ def test_event(self): "extends": "", "n_constraints": 1, "attributes": [ - "exception.type", + "exception.escaped", "exception.message", "exception.stacktrace", - "exception.escaped", + "exception.type", ], } self.semantic_convention_check(event, expected) @@ -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.attrs_by_name["net.peer.port"].ref) + self.assertIsNotNone(client.attrs_by_name["net.peer.port"].attr_type) - self.assertIsNotNone(server.attributes[1].ref) - self.assertIsNotNone(server.attributes[1].attr_type) + self.assertIsNotNone(server.attrs_by_name["net.peer.port"].ref) + self.assertIsNotNone(server.attrs_by_name["net.peer.port"].attr_type) def test_extends(self): semconv = SemanticConventionSet(debug=False) @@ -367,14 +367,14 @@ def test_extends(self): "extends": "", "n_constraints": 0, "attributes": [ - "http.method", - "http.url", - "http.target", + "http.flavor", "http.host", + "http.method", "http.scheme", "http.status_code", "http.status_text", - "http.flavor", + "http.target", + "http.url", "http.user_agent", ], } @@ -385,14 +385,14 @@ def test_extends(self): "extends": "http", "n_constraints": 1, "attributes": [ - "http.method", - "http.url", - "http.target", + "http.flavor", "http.host", + "http.method", "http.scheme", "http.status_code", "http.status_text", - "http.flavor", + "http.target", + "http.url", "http.user_agent", ], } @@ -403,16 +403,16 @@ def test_extends(self): "extends": "http", "n_constraints": 1, "attributes": [ - "http.method", - "http.url", - "http.target", + "http.flavor", "http.host", + "http.method", "http.scheme", + "http.server_name", "http.status_code", "http.status_text", - "http.flavor", + "http.target", + "http.url", "http.user_agent", - "http.server_name", ], } self.semantic_convention_check(list(semconv.models.values())[2], expected) @@ -435,19 +435,19 @@ def test_include(self): "n_constraints": 2, "attributes": [ # Parent - "faas.trigger", "faas.execution", + "faas.trigger", # Include - "http.method", - "http.url", - "http.target", + "http.flavor", "http.host", + "http.method", "http.scheme", + "http.server_name", "http.status_code", "http.status_text", - "http.flavor", + "http.target", + "http.url", "http.user_agent", - "http.server_name", ], } self.semantic_convention_check(faas_http, expected) @@ -458,12 +458,15 @@ def test_deprecation(self): semconv.finish() self.assertEqual(len(semconv.models), 1) - self.assertIsNotNone(list(semconv.models.values())[0].attributes[0].deprecated) + method_attr = list(semconv.models.values())[0].attrs_by_name["http.method"] + self.assertIsNotNone(method_attr.deprecated) self.assertEqual( - list(semconv.models.values())[0].attributes[0].deprecated, + method_attr.deprecated, "Use attribute `nonDepecrated`.", ) - self.assertIsNone(list(semconv.models.values())[0].attributes[3].deprecated) + self.assertIsNone( + list(semconv.models.values())[0].attrs_by_name["http.target"].deprecated + ) def test_stability(self): semconv = SemanticConventionSet(debug=False) @@ -476,33 +479,33 @@ def test_stability(self): self.assertEqual(model.stability, None) attr = model.attributes[0] - self.assertEqual(attr.attr_id, "exp_attr") + self.assertEqual(attr.attr_id, "def_stability") self.assertEqual(attr.stability, StabilityLevel.EXPERIMENTAL) attr = model.attributes[1] - self.assertEqual(attr.attr_id, "stable_attr") - self.assertEqual(attr.stability, StabilityLevel.STABLE) - - attr = model.attributes[2] self.assertEqual(attr.attr_id, "deprecated_attr") self.assertEqual(attr.stability, StabilityLevel.DEPRECATED) - attr = model.attributes[3] - self.assertEqual(attr.attr_id, "def_stability") + attr = model.attributes[2] + self.assertEqual(attr.attr_id, "exp_attr") self.assertEqual(attr.stability, StabilityLevel.EXPERIMENTAL) + attr = model.attributes[3] + self.assertEqual(attr.attr_id, "stable_attr") + self.assertEqual(attr.stability, StabilityLevel.STABLE) + model = list(semconv.models.values())[1] self.assertEqual(len(model.attributes), 2) self.assertEqual(model.stability, StabilityLevel.EXPERIMENTAL) attr = model.attributes[0] - self.assertEqual(attr.attr_id, "test_attr") - self.assertEqual(attr.stability, StabilityLevel.EXPERIMENTAL) - - attr = model.attributes[1] self.assertEqual(attr.attr_id, "dep") self.assertEqual(attr.stability, StabilityLevel.DEPRECATED) + attr = model.attributes[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), 1) self.assertEqual(model.stability, StabilityLevel.DEPRECATED) @@ -570,38 +573,38 @@ def test_inherited_imported(self): self.assertEqual(attrs[0].inherited, False) self.assertEqual(attrs[0].ref, None) - self.assertEqual(attrs[1].fqn, "net.peer.port") + self.assertEqual(attrs[1].fqn, "net.peer.name") self.assertEqual(attrs[1].imported, False) self.assertEqual(attrs[1].inherited, False) self.assertEqual(attrs[1].ref, None) - self.assertEqual(attrs[1].note, "not override") - self.assertEqual(attrs[2].fqn, "net.peer.name") + self.assertEqual(attrs[2].fqn, "net.peer.port") self.assertEqual(attrs[2].imported, False) self.assertEqual(attrs[2].inherited, False) self.assertEqual(attrs[2].ref, None) + self.assertEqual(attrs[2].note, "not override") # Base - rpc attrs = models[2].attributes self.assertEqual(models[2].semconv_id, "rpc") self.assertEqual(len(attrs), 4) - # Included attributes + self.assertEqual(attrs[0].fqn, "net.peer.ip") self.assertEqual(attrs[0].imported, True) self.assertEqual(attrs[0].inherited, False) self.assertEqual(attrs[0].ref, None) - self.assertEqual(attrs[1].fqn, "net.peer.port") + self.assertEqual(attrs[1].fqn, "net.peer.name") self.assertEqual(attrs[1].imported, True) self.assertEqual(attrs[1].inherited, False) self.assertEqual(attrs[1].ref, None) - self.assertEqual(attrs[1].note, "not override") - self.assertEqual(attrs[2].fqn, "net.peer.name") + self.assertEqual(attrs[2].fqn, "net.peer.port") self.assertEqual(attrs[2].imported, True) self.assertEqual(attrs[2].inherited, False) self.assertEqual(attrs[2].ref, None) - # Defined attributes + self.assertEqual(attrs[2].note, "not override") + self.assertEqual(attrs[3].fqn, "rpc.service") self.assertEqual(attrs[3].imported, False) self.assertEqual(attrs[3].inherited, False) @@ -611,44 +614,44 @@ def test_inherited_imported(self): attrs = models[3].attributes self.assertEqual(models[3].semconv_id, "rpc.client") self.assertEqual(len(attrs), 6) - # Parent attributes - self.assertEqual(attrs[0].fqn, "net.peer.ip") + + self.assertEqual(attrs[0].fqn, "http.method") self.assertEqual(attrs[0].imported, True) - self.assertEqual(attrs[0].inherited, True) + self.assertEqual(attrs[0].inherited, False) self.assertEqual(attrs[0].ref, None) - self.assertEqual(attrs[1].fqn, "net.peer.port") - self.assertEqual(attrs[1].imported, False) - self.assertEqual(attrs[1].inherited, False) - self.assertEqual(attrs[1].ref, "net.peer.port") - self.assertEqual(attrs[1].brief, "override") - self.assertEqual(attrs[1].note, "not override") + self.assertEqual(attrs[1].fqn, "net.peer.ip") + self.assertEqual(attrs[1].imported, True) + self.assertEqual(attrs[1].inherited, True) + self.assertEqual(attrs[1].ref, None) self.assertEqual(attrs[2].fqn, "net.peer.name") self.assertEqual(attrs[2].imported, True) self.assertEqual(attrs[2].inherited, True) self.assertEqual(attrs[2].ref, None) - self.assertEqual(attrs[3].fqn, "rpc.service") + self.assertEqual(attrs[3].fqn, "net.peer.port") self.assertEqual(attrs[3].imported, False) - self.assertEqual(attrs[3].inherited, True) - self.assertEqual(attrs[3].ref, None) - # Included attributes - self.assertEqual(attrs[4].fqn, "http.method") - self.assertEqual(attrs[4].imported, True) + self.assertEqual(attrs[3].inherited, False) + self.assertEqual(attrs[3].ref, "net.peer.port") + self.assertEqual(attrs[3].brief, "override") + self.assertEqual(attrs[3].note, "not override") + + self.assertEqual(attrs[4].fqn, "rpc.client.name") + self.assertEqual(attrs[4].imported, False) self.assertEqual(attrs[4].inherited, False) self.assertEqual(attrs[4].ref, None) - # Defined attributes - self.assertEqual(attrs[5].fqn, "rpc.client.name") + + self.assertEqual(attrs[5].fqn, "rpc.service") self.assertEqual(attrs[5].imported, False) - self.assertEqual(attrs[5].inherited, False) + self.assertEqual(attrs[5].inherited, True) self.assertEqual(attrs[5].ref, None) # Include on Extended - zother attrs = models[4].attributes self.assertEqual(models[4].semconv_id, "zother") self.assertEqual(len(attrs), 1) - # Defined attributes + self.assertEqual(attrs[0].fqn, "zother.hostname") self.assertEqual(attrs[0].imported, False) self.assertEqual(attrs[0].inherited, False) @@ -658,46 +661,46 @@ def test_inherited_imported(self): attrs = models[5].attributes self.assertEqual(models[5].semconv_id, "zz.rpc.client") self.assertEqual(len(attrs), 8) - # Parent attributes - self.assertEqual(attrs[0].fqn, "net.peer.ip") + + self.assertEqual(attrs[0].fqn, "http.method") self.assertEqual(attrs[0].imported, True) self.assertEqual(attrs[0].inherited, True) self.assertEqual(attrs[0].ref, None) - self.assertEqual(attrs[1].fqn, "net.peer.port") - self.assertEqual(attrs[1].imported, False) + self.assertEqual(attrs[1].fqn, "net.peer.ip") + self.assertEqual(attrs[1].imported, True) self.assertEqual(attrs[1].inherited, True) - self.assertEqual(attrs[1].ref, "net.peer.port") - self.assertEqual(attrs[1].brief, "override") - self.assertEqual(attrs[1].note, "not override") + self.assertEqual(attrs[1].ref, None) self.assertEqual(attrs[2].fqn, "net.peer.name") self.assertEqual(attrs[2].imported, True) self.assertEqual(attrs[2].inherited, True) self.assertEqual(attrs[2].ref, None) - self.assertEqual(attrs[3].fqn, "rpc.service") + self.assertEqual(attrs[3].fqn, "net.peer.port") self.assertEqual(attrs[3].imported, False) self.assertEqual(attrs[3].inherited, True) - self.assertEqual(attrs[3].ref, None) + self.assertEqual(attrs[3].ref, "net.peer.port") + self.assertEqual(attrs[3].brief, "override") + self.assertEqual(attrs[3].note, "not override") - self.assertEqual(attrs[4].fqn, "http.method") - self.assertEqual(attrs[4].imported, True) + self.assertEqual(attrs[4].fqn, "rpc.client.name") + self.assertEqual(attrs[4].imported, False) self.assertEqual(attrs[4].inherited, True) self.assertEqual(attrs[4].ref, None) - self.assertEqual(attrs[5].fqn, "rpc.client.name") + self.assertEqual(attrs[5].fqn, "rpc.client.zz.attr") self.assertEqual(attrs[5].imported, False) - self.assertEqual(attrs[5].inherited, True) + self.assertEqual(attrs[5].inherited, False) self.assertEqual(attrs[5].ref, None) - # Included attributes - self.assertEqual(attrs[6].fqn, "zother.hostname") - self.assertEqual(attrs[6].imported, True) - self.assertEqual(attrs[6].inherited, False) + + self.assertEqual(attrs[6].fqn, "rpc.service") + self.assertEqual(attrs[6].imported, False) + self.assertEqual(attrs[6].inherited, True) self.assertEqual(attrs[6].ref, None) - # Defined attributes - self.assertEqual(attrs[7].fqn, "rpc.client.zz.attr") - self.assertEqual(attrs[7].imported, False) + + self.assertEqual(attrs[7].fqn, "zother.hostname") + self.assertEqual(attrs[7].imported, True) self.assertEqual(attrs[7].inherited, False) self.assertEqual(attrs[7].ref, None) diff --git a/semantic-conventions/src/tests/semconv/templating/test_markdown.py b/semantic-conventions/src/tests/semconv/templating/test_markdown.py index 540243b4..ed6adba4 100644 --- a/semantic-conventions/src/tests/semconv/templating/test_markdown.py +++ b/semantic-conventions/src/tests/semconv/templating/test_markdown.py @@ -65,6 +65,9 @@ def testEnumInt(self): def testExtendConstraint(self): self.check("markdown/extend_constraint/") + def test_extend_grandparent(self): + self.check("markdown/extend_grandparent/") + def test_error_missing_end(self): ex = self.check("markdown/missing_end_tag/", assert_raises=ValueError) self.assertEqual("Missing ending tag", ex.args[0]) @@ -151,6 +154,9 @@ def test_attribute_group(self): def test_attribute_templates(self): self.check("markdown/attribute_templates/") + def test_sorting(self): + self.check("markdown/sorting/") + def check( self, input_dir: str,