From 91d9c812323b1e1646cdd991b4327a9df0ecf784 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Mon, 29 Jul 2024 20:41:05 -0700 Subject: [PATCH 1/8] Update docs to use weaver for code generation --- .../{libraries.md => code-generation.md} | 122 +++++++++++++----- 1 file changed, 91 insertions(+), 31 deletions(-) rename docs/non-normative/{libraries.md => code-generation.md} (50%) diff --git a/docs/non-normative/libraries.md b/docs/non-normative/code-generation.md similarity index 50% rename from docs/non-normative/libraries.md rename to docs/non-normative/code-generation.md index 320627ed3e..fa450e06cb 100644 --- a/docs/non-normative/libraries.md +++ b/docs/non-normative/code-generation.md @@ -80,44 +80,104 @@ This section contains suggestions on structuring semantic convention artifact(s) ## Generating semantic conventions +This section describes how to do code-generation with weaver. + > Note: -> The tooling used for code generation may change to [opentelemetry-weaver](https://github.com/open-telemetry/weaver), -> without any breaking changes in the generated code and with minimal changes to generation process and templates. +> We're transitioning from [build-tools](https://github.com/open-telemetry/build-tools/blob/main/semantic-conventions/README.md#code-generator) +> to [opentelemetry-weaver](https://github.com/open-telemetry/weaver/blob/main/crates/weaver_forge/README.md) to generate code for semantic conventions. +> All new code-generation should be done using weaver, build-tools may become incompatible with future version of semantic conventions. -The generation is done using [build-tools code generator](https://github.com/open-telemetry/build-tools/blob/main/semantic-conventions/README.md#code-generator). -It's based on YAML definitions of the semantic conventions and uses [Jinja templates](https://palletsprojects.com/p/jinja/). +Code-generation is based on YAML definitions in the specific version of semantic conventions and usually +involves several steps which could be semi-automated: -For example, this Jinja template can be used to generate Python constant for an attribute name along with the docstring. +1. Manually update the Semantic Conventions version in config +2. Add the new Schema URL to the list of supported versions + - If it's not automated, then it can, at least, be automatically checked. +3. Check out (or download) the new version of Semantic Conventions +4. Run code-generation script (see below for the details) +5. Fix lint violations in the auto-generated code (if any) +6. Send the PR with new code to the corresponding repository -```jinja -{{attribute.fqn | to_const_name}} = "{{attribute.fqn}}" -""" -{{attribute.brief | to_doc_brief}}. -{%- if attribute.note %} -Note: {{attribute.note | to_doc_brief | indent}}. -{%- endif %} -""" -``` +Here are examples of how steps 2-5 are implemented for [Python](https://github.com/open-telemetry/opentelemetry-python/pull/4091) and [Erlang](https://github.com/open-telemetry/opentelemetry-erlang/pull/733). + +Step 4 (running code generation) depends on language-specific customizations. It's also the only step that's affected by tooling migration. + +Check out[weaver code-generation documentation for the details](https://github.com/open-telemetry/weaver/blob/main/crates/weaver_forge/README.md) + +### Migrating from build-tools + +Migration from build-tools involves changing Jinja templates and adding [weaver config file](https://github.com/open-telemetry/weaver/blob/main/crates/weaver_forge/README.md#configuration-file---weaveryaml). + +#### Weaver config + +Here's a simplified example of this file that generates all attributes. -It generates the following code: +```yaml +params: + excluded_namespaces: [ios, aspnetcore, signalr, android, dotnet, jvm, kestrel] -```python -SERVER_ADDRESS = "server.address" -""" -Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. -Note: When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. -""" +templates: + - pattern: semantic_attributes.j2 + filter: > + semconv_grouped_attributes({ + "exclude_root_namespace": $excluded_namespaces + }) + | map({ + root_namespace: .root_namespace, + attributes: .attributes, + output: $output + }) + application_mode: each ``` -Language SIGs are expected to create Jinja templates specific to their language. -Code-generation usually involves several steps which could be semi-automated: +You can configure language-specific parameters in the `params` section of the config or pass them with `--param key=value` arguments when +running weaver command from the code generation script (similarly to build-tools `-Dparam=value` option). -1. Manually update the Semantic Conventions version when necessary -2. Add the new Schema URL to the list of supported versions - - If it's not automated, then it can, at least, be automatically checked. -3. Check out (or download) this version of Semantic Conventions -4. Run code-generation script for each template -5. Fix lint violations in the auto-generated code (if any) -6. Send the PR with new code to the corresponding repository +Weaver is able to run code-generation for multiple templates (defined in the corresponding section) at once. + +Before executing Jinja, weaver allows to filter or process semantic convention definitions in `filter` section for each template. +In this example it uses `semconv_grouped_attributes` filter - a helper method that groups attribute definitions by root namespace and excludes +attributes not relevant to this language. You can write alternative or additional filters and massage semantic conventions data using [JQ](https://jqlang.github.io/jq/manual/). + +The `application_mode: each` configures weaver to run code generation for each semconv group and, as a consequence, generate code for each group +in a different file. + +See +[weaver code-generation docs](https://github.com/open-telemetry/weaver/blob/main/crates/weaver_forge/README.md) for the details on the config, data schema, JQ filters, and more. + +#### Jinja templates + +Jinja templates need to be changed to leverage (better) data structure and helper methods. +The first key difference is that each jinja template should define how to name the corresponding file(s). + +E.g. here's an example that uses root namespace in a subfolder provided in the `output` parameter. + +```jinja +{% set file_name = ctx.output + (ctx.root_namespace | snake_case ) ~ "_attributes.py" -%} +{{- template.set_file_name(file_name) -}} +``` -Here are examples of how steps 2-5 are implemented for [Java](https://github.com/open-telemetry/semantic-conventions-java/blob/7da24068eea69dff11a78d59750b115dc4c5854d/build.gradle.kts#L55-L137) and [Python](https://github.com/open-telemetry/opentelemetry-python/blob/397e357dfad3e6ff42c09c74d5945dfdcad24bdd/scripts/semconv/generate.sh). +Notable changes on data structure: + +- `attributes_and_templates` -> `ctx.attributes` +- `enum_attributes` -> `ctx.attributes | select("enum")` +- `metrics` -> `ctx.metrics` +- `root_namespace` -> `ctx.root_namespace` (only available if using `semconv_grouped_attributes` or similar filter)' +- all custom parameters are provided as properties under `ctx` variable. +- `attribute.fqn` -> `attribute.name` +- `attribute.type | instantiated_type` (gets underlying type of enum values) +- `attribute.attr_type.members` -> `attribute.type.members` (gets members of enum type) +- `member.member_id` -> `member.id` (gets id of the enum member) + +Notable changes on helper methods: +- `attr.fqn | to_const_name` -> `attr.name | screaming_snake_case` +- `attr.fqn | to_camelcase(True) -> attr.name | pascal_case` +- `attr.brief | to_doc_brief | indent ` -> `attr.brief | comment_with_prefix(" ")` (prefix is used to indent) +- stability/deprecation checks: + - `attribute is stable` if checking one attribute, `attributes | select("stable")` to filter stable attributes + - `attribute is experimental` if checking one attribute, `attributes | select("experimental")` to filter experimental attributes + - `attribute is deprecated` if checking one attribute, `attributes | select("deprecated")` to filter deprecated attributes +- check if attribute is a template: `attribute.type is template_type` +- `print_member_value` - no replacement at this time, use something like `{%- if type == "string" -%}"{{value}}"{%-else-%}{{value}}{%-endif-%}` +- new ways to simplify switch-like logic: `key | map_text("map_name")`. Maps can be defined in the weaver config. + It can be very useful to convert semantic convention attribute types to language-specific types. From 5794394ab1ce7c53d5a050c5c9041cdf84d175ce Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Mon, 29 Jul 2024 20:45:40 -0700 Subject: [PATCH 2/8] changelog --- .chloggen/1296.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .chloggen/1296.yaml diff --git a/.chloggen/1296.yaml b/.chloggen/1296.yaml new file mode 100644 index 0000000000..9427105e4f --- /dev/null +++ b/.chloggen/1296.yaml @@ -0,0 +1,4 @@ +change_type: enhancement +component: other +note: Update semantic conventions code generation documentation to use weaver instead of build-tools. +issues: [ 1296 ] From e21ca0040e1642a8dcd38d97dfa5ee62a94ca093 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Mon, 29 Jul 2024 20:47:05 -0700 Subject: [PATCH 3/8] up --- docs/non-normative/code-generation.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/non-normative/code-generation.md b/docs/non-normative/code-generation.md index fa450e06cb..d4b8a1acf1 100644 --- a/docs/non-normative/code-generation.md +++ b/docs/non-normative/code-generation.md @@ -11,6 +11,9 @@ linkTitle: Libraries - [Deprecated Conventions](#deprecated-conventions) - [Semantic Conventions Artifact Structure](#semantic-conventions-artifact-structure) - [Generating semantic conventions](#generating-semantic-conventions) + - [Migrating from build-tools](#migrating-from-build-tools) + - [Weaver config](#weaver-config) + - [Jinja templates](#jinja-templates) @@ -170,6 +173,7 @@ Notable changes on data structure: - `member.member_id` -> `member.id` (gets id of the enum member) Notable changes on helper methods: + - `attr.fqn | to_const_name` -> `attr.name | screaming_snake_case` - `attr.fqn | to_camelcase(True) -> attr.name | pascal_case` - `attr.brief | to_doc_brief | indent ` -> `attr.brief | comment_with_prefix(" ")` (prefix is used to indent) From 58a6e18b7cdefe04cc902951485d19c1ce6f19cd Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Tue, 30 Jul 2024 09:44:36 -0700 Subject: [PATCH 4/8] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Joao Grassi <5938087+joaopgrassi@users.noreply.github.com> Co-authored-by: Laurent Quérel --- docs/non-normative/code-generation.md | 28 +++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/docs/non-normative/code-generation.md b/docs/non-normative/code-generation.md index d4b8a1acf1..77996155cb 100644 --- a/docs/non-normative/code-generation.md +++ b/docs/non-normative/code-generation.md @@ -22,7 +22,7 @@ The code for OpenTelemetry Semantic Conventions defined in this repository can b OpenTelemetry Language SIGs can generate Semantic Conventions code in the form that's idiomatic for their language and may (or may not) ship it as a stand-alone library. -This document outlines common patterns and provides non-normative guidance on how to structure semantic conventions artifact +This document outlines common patterns and provides non-normative guidance on how to structure semantic conventions artifacts and generate the code. ## Stability and Versioning @@ -55,11 +55,11 @@ the `deprecated` property that describes deprecation reason which can be used to and breaking changes in user applications. Keep stable convention definitions inside the preview (part of) semantic conversions artifact. It prevents user code from breaking when semantic convention stabilizes. Deprecate stable definitions inside the preview artifact and point users to the stable location in generated documentation. -For example, in Java `http.request.method` attribute is defined as the deprecated `io.opentelemetry.semconv.incubating.HttpIncubatingAttributes.HTTP_REQUEST_METHOD` field and also as stable `io.opentelemetry.semconv.HttpAttributes.HTTP_REQUEST_METHOD`. +For example, in Java, the attribute `http.request.method` is defined as the deprecated in both stable and preview artifacts (e.g., `io.opentelemetry.semconv.incubating.HttpIncubatingAttributes.HTTP_REQUEST_METHOD`, `io.opentelemetry.semconv.HttpAttributes.HTTP_REQUEST_METHOD`). ## Semantic Conventions Artifact Structure -This section contains suggestions on structuring semantic convention artifact(s) which should be adjusted to the specific language. +This section contains suggestions on how to structure semantic convention artifact(s). - Artifact name: - `opentelemetry-semconv` - stable conventions @@ -85,12 +85,13 @@ This section contains suggestions on structuring semantic convention artifact(s) This section describes how to do code-generation with weaver. -> Note: +> [!IMPORTANT] > We're transitioning from [build-tools](https://github.com/open-telemetry/build-tools/blob/main/semantic-conventions/README.md#code-generator) > to [opentelemetry-weaver](https://github.com/open-telemetry/weaver/blob/main/crates/weaver_forge/README.md) to generate code for semantic conventions. > All new code-generation should be done using weaver, build-tools may become incompatible with future version of semantic conventions. -Code-generation is based on YAML definitions in the specific version of semantic conventions and usually +Code-generation is based on YAML definitions in the specific version of semantic conventions. +Usually, it involves several steps where some can be semi-automated: involves several steps which could be semi-automated: 1. Manually update the Semantic Conventions version in config @@ -105,11 +106,11 @@ Here are examples of how steps 2-5 are implemented for [Python](https://github.c Step 4 (running code generation) depends on language-specific customizations. It's also the only step that's affected by tooling migration. -Check out[weaver code-generation documentation for the details](https://github.com/open-telemetry/weaver/blob/main/crates/weaver_forge/README.md) +Check out [weaver code-generation documentation for more details](https://github.com/open-telemetry/weaver/blob/main/crates/weaver_forge/README.md) ### Migrating from build-tools -Migration from build-tools involves changing Jinja templates and adding [weaver config file](https://github.com/open-telemetry/weaver/blob/main/crates/weaver_forge/README.md#configuration-file---weaveryaml). +Migration from build-tools involves changing Jinja templates and adding a [weaver config file](https://github.com/open-telemetry/weaver/blob/main/crates/weaver_forge/README.md#configuration-file---weaveryaml). #### Weaver config @@ -138,20 +139,23 @@ running weaver command from the code generation script (similarly to build-tools Weaver is able to run code-generation for multiple templates (defined in the corresponding section) at once. -Before executing Jinja, weaver allows to filter or process semantic convention definitions in `filter` section for each template. -In this example it uses `semconv_grouped_attributes` filter - a helper method that groups attribute definitions by root namespace and excludes +Before executing Jinja, weaver allows to filter or process semantic convention definitions in the `filter` section for each template. +In this example, it uses `semconv_grouped_attributes` filter - a helper method that groups attribute definitions by root namespace and excludes attributes not relevant to this language. You can write alternative or additional filters and massage semantic conventions data using [JQ](https://jqlang.github.io/jq/manual/). The `application_mode: each` configures weaver to run code generation for each semconv group and, as a consequence, generate code for each group -in a different file. +in a different file. The application mode `single` is also supported to apply the template to all groups at once. See -[weaver code-generation docs](https://github.com/open-telemetry/weaver/blob/main/crates/weaver_forge/README.md) for the details on the config, data schema, JQ filters, and more. +[weaver code-generation docs](https://github.com/open-telemetry/weaver/blob/main/crates/weaver_forge/README.md) +for the details on the config, data schema, JQ filters, and more. #### Jinja templates Jinja templates need to be changed to leverage (better) data structure and helper methods. -The first key difference is that each jinja template should define how to name the corresponding file(s). +The first key difference is that each jinja template can define how to name the corresponding file(s). If you +don't specify the name of the output file via the method `set_file_name`, Weaver will use the relative path +and the name of the template itself to determine the output file. E.g. here's an example that uses root namespace in a subfolder provided in the `output` parameter. From 87559ade1d94e43b0cc3c8dfa5e543afc49c38ed Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Tue, 30 Jul 2024 11:16:05 -0700 Subject: [PATCH 5/8] review 2 --- .chloggen/1296.yaml | 2 +- .github/ISSUE_TEMPLATE/bug_report.yaml | 1 + docs/non-normative/code-generation.md | 10 ++++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.chloggen/1296.yaml b/.chloggen/1296.yaml index 9427105e4f..8a1347f20a 100644 --- a/.chloggen/1296.yaml +++ b/.chloggen/1296.yaml @@ -1,4 +1,4 @@ change_type: enhancement -component: other +component: docs note: Update semantic conventions code generation documentation to use weaver instead of build-tools. issues: [ 1296 ] diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 40af0a175b..0f888909e0 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -16,6 +16,7 @@ body: multiple: true options: - area:other + - area:docs # NOTE: The list below is autogenerated using `make generate-gh-issue-templates` # DO NOT manually edit it. # Start semconv area list diff --git a/docs/non-normative/code-generation.md b/docs/non-normative/code-generation.md index 77996155cb..915ff4a738 100644 --- a/docs/non-normative/code-generation.md +++ b/docs/non-normative/code-generation.md @@ -63,7 +63,7 @@ This section contains suggestions on how to structure semantic convention artifa - Artifact name: - `opentelemetry-semconv` - stable conventions - - `opentelemetry-semconv-incubating` - (if applicable) the preview artifact containing all conventions + - `opentelemetry-semconv-incubating` - (if applicable) the preview artifact containing all (stable and experimental) conventions - Namespace: `opentelemetry.semconv` and `opentelemetry.semconv.incubating` - All supported Schema URLs should be listed to allow different instrumentations in the same application to provide the exact version of conventions they follow. - Attributes, metrics, and other convention definitions should be grouped by the convention type and the root namespace. See the example below: @@ -129,13 +129,13 @@ templates: | map({ root_namespace: .root_namespace, attributes: .attributes, - output: $output + output: $output + "attributes/" }) application_mode: each ``` -You can configure language-specific parameters in the `params` section of the config or pass them with `--param key=value` arguments when -running weaver command from the code generation script (similarly to build-tools `-Dparam=value` option). +You can configure language-specific parameters in the `params` section of the config or pass them with `-DparamName=value` arguments when +running weaver command from the code generation script (similarly to build-tools). Weaver is able to run code-generation for multiple templates (defined in the corresponding section) at once. @@ -143,6 +143,8 @@ Before executing Jinja, weaver allows to filter or process semantic convention d In this example, it uses `semconv_grouped_attributes` filter - a helper method that groups attribute definitions by root namespace and excludes attributes not relevant to this language. You can write alternative or additional filters and massage semantic conventions data using [JQ](https://jqlang.github.io/jq/manual/). +In certain cases, calling `semconv_grouped_attributes` with namespace exclusion and stability filters may be enough and then no port-processing is necessary. + The `application_mode: each` configures weaver to run code generation for each semconv group and, as a consequence, generate code for each group in a different file. The application mode `single` is also supported to apply the template to all groups at once. From bd3d35eedf914d1bfe77a5105b387e197d0f5b82 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Tue, 30 Jul 2024 11:28:49 -0700 Subject: [PATCH 6/8] review 3 --- docs/non-normative/code-generation.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/non-normative/code-generation.md b/docs/non-normative/code-generation.md index 915ff4a738..42c2266e09 100644 --- a/docs/non-normative/code-generation.md +++ b/docs/non-normative/code-generation.md @@ -1,9 +1,9 @@ -# Semantic convention libraries +# Generating Semantic Convention libraries @@ -85,7 +85,7 @@ This section contains suggestions on how to structure semantic convention artifa This section describes how to do code-generation with weaver. -> [!IMPORTANT] +> [!IMPORTANT] > We're transitioning from [build-tools](https://github.com/open-telemetry/build-tools/blob/main/semantic-conventions/README.md#code-generator) > to [opentelemetry-weaver](https://github.com/open-telemetry/weaver/blob/main/crates/weaver_forge/README.md) to generate code for semantic conventions. > All new code-generation should be done using weaver, build-tools may become incompatible with future version of semantic conventions. @@ -145,11 +145,11 @@ attributes not relevant to this language. You can write alternative or additiona In certain cases, calling `semconv_grouped_attributes` with namespace exclusion and stability filters may be enough and then no port-processing is necessary. -The `application_mode: each` configures weaver to run code generation for each semconv group and, as a consequence, generate code for each group -in a different file. The application mode `single` is also supported to apply the template to all groups at once. +The `application_mode: each` configures weaver to run code generation for each semantic convention group and, as a consequence, +generate code for each group in a different file. The application mode `single` is also supported to apply the template to all groups at once. See -[weaver code-generation docs](https://github.com/open-telemetry/weaver/blob/main/crates/weaver_forge/README.md) +[weaver code-generation docs](https://github.com/open-telemetry/weaver/blob/main/crates/weaver_forge/README.md) for the details on the config, data schema, JQ filters, and more. #### Jinja templates @@ -181,13 +181,13 @@ Notable changes on data structure: Notable changes on helper methods: - `attr.fqn | to_const_name` -> `attr.name | screaming_snake_case` -- `attr.fqn | to_camelcase(True) -> attr.name | pascal_case` -- `attr.brief | to_doc_brief | indent ` -> `attr.brief | comment_with_prefix(" ")` (prefix is used to indent) +- `attr.fqn | to_camelcase(True)` -> `attr.name | pascal_case` +- `attr.brief | to_doc_brief | indent` -> `attr.brief | comment_with_prefix(" ")` (prefix is used to indent) - stability/deprecation checks: - `attribute is stable` if checking one attribute, `attributes | select("stable")` to filter stable attributes - `attribute is experimental` if checking one attribute, `attributes | select("experimental")` to filter experimental attributes - `attribute is deprecated` if checking one attribute, `attributes | select("deprecated")` to filter deprecated attributes - check if attribute is a template: `attribute.type is template_type` - `print_member_value` - no replacement at this time, use something like `{%- if type == "string" -%}"{{value}}"{%-else-%}{{value}}{%-endif-%}` -- new ways to simplify switch-like logic: `key | map_text("map_name")`. Maps can be defined in the weaver config. +- new way to simplify switch-like logic: `key | map_text("map_name")`. Maps can be defined in the weaver config. It can be very useful to convert semantic convention attribute types to language-specific types. From d6d1e4bdaac5ee93aa508b4da7761e1921d699c2 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Tue, 30 Jul 2024 11:36:27 -0700 Subject: [PATCH 7/8] up --- docs/non-normative/code-generation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/non-normative/code-generation.md b/docs/non-normative/code-generation.md index 42c2266e09..4ca5f9627c 100644 --- a/docs/non-normative/code-generation.md +++ b/docs/non-normative/code-generation.md @@ -143,7 +143,7 @@ Before executing Jinja, weaver allows to filter or process semantic convention d In this example, it uses `semconv_grouped_attributes` filter - a helper method that groups attribute definitions by root namespace and excludes attributes not relevant to this language. You can write alternative or additional filters and massage semantic conventions data using [JQ](https://jqlang.github.io/jq/manual/). -In certain cases, calling `semconv_grouped_attributes` with namespace exclusion and stability filters may be enough and then no port-processing is necessary. +In certain cases, calling `semconv_grouped_attributes` with namespace exclusion and stability filters may be enough and post-processing is not necessary. The `application_mode: each` configures weaver to run code generation for each semantic convention group and, as a consequence, generate code for each group in a different file. The application mode `single` is also supported to apply the template to all groups at once. From 831184957e447ef6f8578d6949375ba31c08f092 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Wed, 31 Jul 2024 22:11:37 -0700 Subject: [PATCH 8/8] Update docs/non-normative/code-generation.md Co-authored-by: Joao Grassi <5938087+joaopgrassi@users.noreply.github.com> --- docs/non-normative/code-generation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/non-normative/code-generation.md b/docs/non-normative/code-generation.md index 4ca5f9627c..e8e22d8848 100644 --- a/docs/non-normative/code-generation.md +++ b/docs/non-normative/code-generation.md @@ -55,7 +55,7 @@ the `deprecated` property that describes deprecation reason which can be used to and breaking changes in user applications. Keep stable convention definitions inside the preview (part of) semantic conversions artifact. It prevents user code from breaking when semantic convention stabilizes. Deprecate stable definitions inside the preview artifact and point users to the stable location in generated documentation. -For example, in Java, the attribute `http.request.method` is defined as the deprecated in both stable and preview artifacts (e.g., `io.opentelemetry.semconv.incubating.HttpIncubatingAttributes.HTTP_REQUEST_METHOD`, `io.opentelemetry.semconv.HttpAttributes.HTTP_REQUEST_METHOD`). +For example, in Java, the attribute `http.request.method` is defined as deprecated in both stable and preview artifacts (e.g., `io.opentelemetry.semconv.incubating.HttpIncubatingAttributes.HTTP_REQUEST_METHOD`, `io.opentelemetry.semconv.HttpAttributes.HTTP_REQUEST_METHOD`). ## Semantic Conventions Artifact Structure