diff --git a/.chloggen/add-dubbo-rpc-semconv.yaml b/.chloggen/add-dubbo-rpc-semconv.yaml new file mode 100644 index 0000000000..153e0af6c0 --- /dev/null +++ b/.chloggen/add-dubbo-rpc-semconv.yaml @@ -0,0 +1,20 @@ +# If your change doesn't affect end users you should instead start +# your pull request title with [chore] or use the "Skip Changelog" label. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: enhancement + +# The name of the area of concern in the attributes-registry, (e.g. http, cloud, db) +component: rpc + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add semantic conventions for Apache Dubbo RPC system. + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +# The values here must be integers. +issues: [3291] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: diff --git a/docs/rpc/README.md b/docs/rpc/README.md index 3a410f8b66..12ea4938ab 100644 --- a/docs/rpc/README.md +++ b/docs/rpc/README.md @@ -43,6 +43,7 @@ Semantic conventions for RPC are defined for the following signals: Technology specific semantic conventions are defined for the following RPC systems: * [Connect](connect-rpc.md): Semantic Conventions for *Connect RPC*. +* [Dubbo](dubbo.md): Semantic Conventions for *Apache Dubbo*. * [gRPC](grpc.md): Semantic Conventions for *gRPC*. * [JSON-RPC](json-rpc.md): Semantic Conventions for *JSON-RPC*. diff --git a/docs/rpc/dubbo.md b/docs/rpc/dubbo.md new file mode 100644 index 0000000000..fa0f41a1e7 --- /dev/null +++ b/docs/rpc/dubbo.md @@ -0,0 +1,309 @@ + + +# Semantic conventions for Apache Dubbo + +**Status**: [Development][DocumentStatus] + + + +- [Spans](#spans) + - [Client](#client) + - [Server](#server) +- [Metrics](#metrics) + + + +The Semantic Conventions for [Apache Dubbo](https://dubbo.apache.org/) extend and override the [RPC Semantic Conventions](README.md). + +## Spans + +### Client + + + + + + +**Status:** ![Development](https://img.shields.io/badge/-development-blue) + +This span represents an outgoing Remote Procedure Call (RPC). + +`rpc.system.name` MUST be set to `"dubbo"` and SHOULD be provided **at span creation time.** + +**Span name:** refer to the [Span Name](/docs/rpc/rpc-spans.md#name) section. + +**Span kind** MUST be `CLIENT`. + +**Span status** Refer to the [Recording Errors](/docs/general/recording-errors.md) +document for details on how to record span status. See also `rpc.response.status_code` attribute +for the details on which values classify as errors. + +**Attributes:** + +| Key | Stability | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Value Type | Description | Example Values | +| --- | --- | --- | --- | --- | --- | +| [`rpc.method`](/docs/registry/attributes/rpc.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | The fully-qualified logical name of the method from the RPC interface perspective. [1] | `com.example.ExampleService/exampleMethod`; `EchoService/Echo`; `_OTHER` | +| [`rpc.response.status_code`](/docs/registry/attributes/rpc.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | The string representation of the Dubbo response status code returned by the server or generated by the client. [2] | `OK`; `DEADLINE_EXCEEDED`; `SERVER_ERROR` | +| [`error.type`](/docs/registry/attributes/error.md) | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | `Conditionally Required` If and only if the operation failed. | string | Describes a class of error the operation ended with. [3] | `DEADLINE_EXCEEDED`; `java.net.UnknownHostException`; `-32602` | +| [`rpc.method_original`](/docs/registry/attributes/rpc.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Conditionally Required` If and only if it's different than `rpc.method`. | string | The original name of the method used by the client. | `com.myservice.EchoService/catchAll`; `com.myservice.EchoService/unknownMethod`; `InvalidMethod` | +| [`server.address`](/docs/registry/attributes/server.md) | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | `Conditionally Required` If available. | string | RPC server [host name](https://grpc.github.io/grpc/core/md_doc_naming.html). [4] | `192.168.1.100`; `api.example.com` | +| [`server.port`](/docs/registry/attributes/server.md) | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | `Conditionally Required` [5] | int | Server port number. [6] | `20880`; `50051` | +| [`network.peer.address`](/docs/registry/attributes/network.md) | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | `Recommended` | string | Peer address of the network connection - IP address or Unix domain socket name. [7] | `10.1.2.80`; `/tmp/my.sock` | +| [`network.peer.port`](/docs/registry/attributes/network.md) | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | `Recommended` If `network.peer.address` is set. | int | Peer port number of the network connection. | `65123` | +| [`rpc.request.metadata.`](/docs/registry/attributes/rpc.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Opt-In` | string[] | RPC request metadata, `` being the normalized RPC metadata key (lowercase), the value being the metadata values. [8] | `["1.2.3.4", "1.2.3.5"]` | +| [`rpc.response.metadata.`](/docs/registry/attributes/rpc.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Opt-In` | string[] | RPC response metadata, `` being the normalized RPC metadata key (lowercase), the value being the metadata values. [9] | `["attribute_value"]` | + +**[1] `rpc.method`:** The method name MAY have unbounded cardinality in edge or error cases. + +Some RPC frameworks or libraries provide a fixed set of recognized methods +for client stubs and server implementations. Instrumentations for such +frameworks MUST set this attribute to the original method name only +when the method is recognized by the framework or library. + +When the method is not recognized, for example, when the server receives +a request for a method that is not predefined on the server, or when +instrumentation is not able to reliably detect if the method is predefined, +the attribute MUST be set to `_OTHER`. In such cases, tracing +instrumentations MUST also set `rpc.method_original` attribute to +the original method value. + +If the RPC instrumentation could end up converting valid RPC methods to +`_OTHER`, then it SHOULD provide a way to configure the list of recognized +RPC methods. + +The `rpc.method` can be different from the name of any implementing +method/function. +The `code.function.name` attribute may be used to record the fully-qualified +method actually executing the call on the server side, or the +RPC client stub method on the client side. + +**[2] `rpc.response.status_code`:** All status codes except `OK` SHOULD be considered errors. + +Status codes reference: + +- Dubbo2: [Dubbo2 Protocol Status Codes](https://dubbo.apache.org/en/overview/reference/protocols/tcp/#protocol-specification) +- Dubbo3 Triple protocol: [Triple Protocol Error Codes](https://dubbo.apache.org/en/overview/reference/protocols/triple-spec/#311-request) + +**[3] `error.type`:** If the RPC fails with an error before status code is returned, +`error.type` SHOULD be set to the exception type (its fully-qualified class name, if applicable) +or a component-specific, low cardinality error identifier. + +If a response status code is returned and status indicates an error, +`error.type` SHOULD be set to that status code. Check system-specific conventions +for the details on which values of `rpc.response.status_code` are considered errors. + +The `error.type` value SHOULD be predictable and SHOULD have low cardinality. +Instrumentations SHOULD document the list of errors they report. + +If the request has completed successfully, instrumentations SHOULD NOT set +`error.type`. + +**[4] `server.address`:** Instrumentations SHOULD populate `server.address` (along with `server.port`) +based on the configuration used when creating the Dubbo client and +SHOULD NOT use actual network-level connection information for this purpose +to ensure low cardinality. + +The Dubbo registry address SHOULD NOT be used as `server.address`. Instead, use +the address of the actual server being called. + +- Given the target URL `dubbo://192.168.1.100:20880/com.example.DemoService`, expected attributes: + - `server.address`: `"192.168.1.100"` + - `server.port`: `20880` +- Given the target URL `tri://api.example.com:50051/com.example.GreeterService`, expected attributes: + - `server.address`: `"api.example.com"` + - `server.port`: `50051` +- Given the target URL `tri://api.example.com/com.example.GreeterService` (port not specified), expected attributes: + - `server.address`: `"api.example.com"` + - `server.port`: not set + +When the address is an IP address, instrumentations SHOULD NOT do a +reverse proxy lookup to obtain a DNS name and SHOULD set `server.address` +to the IP address provided. + +**[5] `server.port`:** if `server.address` is set and if the port is supported by the network transport used for communication. + +**[6] `server.port`:** See the `server.address` for details on parsing the target string. + +**[7] `network.peer.address`:** If a RPC involved multiple network calls (for example retries), the last contacted address SHOULD be used. + +**[8] `rpc.request.metadata.`:** Instrumentations SHOULD require an explicit configuration of which metadata values are to be captured. +Including all request metadata values can be a security risk - explicit configuration helps avoid leaking sensitive information. + +For example, a property `my-custom-key` with value `["1.2.3.4", "1.2.3.5"]` SHOULD be recorded as +`rpc.request.metadata.my-custom-key` attribute with value `["1.2.3.4", "1.2.3.5"]` + +**[9] `rpc.response.metadata.`:** Instrumentations SHOULD require an explicit configuration of which metadata values are to be captured. +Including all response metadata values can be a security risk - explicit configuration helps avoid leaking sensitive information. + +For example, a property `my-custom-key` with value `["attribute_value"]` SHOULD be recorded as +the `rpc.response.metadata.my-custom-key` attribute with value `["attribute_value"]` + +The following attributes can be important for making sampling decisions +and SHOULD be provided **at span creation time** (if provided at all): + +* [`rpc.method`](/docs/registry/attributes/rpc.md) +* [`server.address`](/docs/registry/attributes/server.md) +* [`server.port`](/docs/registry/attributes/server.md) + +--- + +`error.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. + +| Value | Description | Stability | +| --- | --- | --- | +| `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + + + + + +### Server + + + + + + +**Status:** ![Development](https://img.shields.io/badge/-development-blue) + +This span represents an incoming Remote Procedure Call (RPC). + +`rpc.system.name` MUST be set to `"dubbo"` and SHOULD be provided **at span creation time.** + +**Span name:** refer to the [Span Name](/docs/rpc/rpc-spans.md#name) section. + +**Span kind** MUST be `SERVER`. + +**Span status** Refer to the [Recording Errors](/docs/general/recording-errors.md) +document for details on how to record span status. See also `rpc.response.status_code` attribute +for the details on which values classify as errors. + +**Attributes:** + +| Key | Stability | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Value Type | Description | Example Values | +| --- | --- | --- | --- | --- | --- | +| [`rpc.response.status_code`](/docs/registry/attributes/rpc.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | The string representation of the Dubbo response status code returned by the server. [1] | `OK`; `SERVER_ERROR`; `SERVER_THREADPOOL_EXHAUSTED_ERROR` | +| [`error.type`](/docs/registry/attributes/error.md) | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | `Conditionally Required` If and only if the operation failed. | string | Describes a class of error the operation ended with. [2] | `DEADLINE_EXCEEDED`; `java.net.UnknownHostException`; `-32602` | +| [`rpc.method`](/docs/registry/attributes/rpc.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Conditionally Required` if available. | string | The fully-qualified logical name of the method from the RPC interface perspective. [3] | `com.example.ExampleService/exampleMethod`; `EchoService/Echo`; `_OTHER` | +| [`rpc.method_original`](/docs/registry/attributes/rpc.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Conditionally Required` If and only if it's different than `rpc.method`. | string | The original name of the method used by the client. | `com.myservice.EchoService/catchAll`; `com.myservice.EchoService/unknownMethod`; `InvalidMethod` | +| [`server.address`](/docs/registry/attributes/server.md) | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | `Conditionally Required` If available. | string | RPC server [host name](https://grpc.github.io/grpc/core/md_doc_naming.html). [4] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | +| [`server.port`](/docs/registry/attributes/server.md) | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | `Conditionally Required` [5] | int | Server port number. [6] | `80`; `8080`; `443` | +| [`client.address`](/docs/registry/attributes/client.md) | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | `Recommended` | string | Client address - domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [7] | `client.example.com`; `10.1.2.80`; `/tmp/my.sock` | +| [`client.port`](/docs/registry/attributes/client.md) | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | `Recommended` | int | Client port number. [8] | `65123` | +| [`network.peer.address`](/docs/registry/attributes/network.md) | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | `Recommended` | string | Peer address of the network connection - IP address or Unix domain socket name. [9] | `10.1.2.80`; `/tmp/my.sock` | +| [`network.peer.port`](/docs/registry/attributes/network.md) | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | `Recommended` If `network.peer.address` is set. | int | Peer port number of the network connection. | `65123` | +| [`rpc.request.metadata.`](/docs/registry/attributes/rpc.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Opt-In` | string[] | RPC request metadata, `` being the normalized RPC metadata key (lowercase), the value being the metadata values. [10] | `["1.2.3.4", "1.2.3.5"]` | +| [`rpc.response.metadata.`](/docs/registry/attributes/rpc.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Opt-In` | string[] | RPC response metadata, `` being the normalized RPC metadata key (lowercase), the value being the metadata values. [11] | `["attribute_value"]` | + +**[1] `rpc.response.status_code`:** For Dubbo2, the following status codes SHOULD be considered errors: + +- `SERVER_ERROR` +- `SERVER_THREADPOOL_EXHAUSTED_ERROR` +- `SERVER_TIMEOUT` +- `SERVICE_ERROR` + +For Dubbo3 Triple protocol, the following status codes SHOULD be considered errors: + +- `DATA_LOSS` +- `DEADLINE_EXCEEDED` +- `INTERNAL` +- `UNAVAILABLE` +- `UNIMPLEMENTED` +- `UNKNOWN` + +Status codes reference: + +- Dubbo2: [Dubbo2 Protocol Status Codes](https://dubbo.apache.org/en/overview/reference/protocols/tcp/#protocol-specification) +- Dubbo3 Triple protocol: [Triple Protocol Error Codes](https://dubbo.apache.org/en/overview/reference/protocols/triple-spec/#311-request) + +**[2] `error.type`:** If the RPC fails with an error before status code is returned, +`error.type` SHOULD be set to the exception type (its fully-qualified class name, if applicable) +or a component-specific, low cardinality error identifier. + +If a response status code is returned and status indicates an error, +`error.type` SHOULD be set to that status code. Check system-specific conventions +for the details on which values of `rpc.response.status_code` are considered errors. + +The `error.type` value SHOULD be predictable and SHOULD have low cardinality. +Instrumentations SHOULD document the list of errors they report. + +If the request has completed successfully, instrumentations SHOULD NOT set +`error.type`. + +**[3] `rpc.method`:** The method name MAY have unbounded cardinality in edge or error cases. + +Some RPC frameworks or libraries provide a fixed set of recognized methods +for client stubs and server implementations. Instrumentations for such +frameworks MUST set this attribute to the original method name only +when the method is recognized by the framework or library. + +When the method is not recognized, for example, when the server receives +a request for a method that is not predefined on the server, or when +instrumentation is not able to reliably detect if the method is predefined, +the attribute MUST be set to `_OTHER`. In such cases, tracing +instrumentations MUST also set `rpc.method_original` attribute to +the original method value. + +If the RPC instrumentation could end up converting valid RPC methods to +`_OTHER`, then it SHOULD provide a way to configure the list of recognized +RPC methods. + +The `rpc.method` can be different from the name of any implementing +method/function. +The `code.function.name` attribute may be used to record the fully-qualified +method actually executing the call on the server side, or the +RPC client stub method on the client side. + +**[4] `server.address`:** May contain server IP address, DNS name, or local socket name. When host component is an IP address, instrumentations SHOULD NOT do a reverse proxy lookup to obtain DNS name and SHOULD set `server.address` to the IP address provided in the host component. + +**[5] `server.port`:** if `server.address` is set and if the port is supported by the network transport used for communication. + +**[6] `server.port`:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. + +**[7] `client.address`:** When observed from the server side, and when communicating through an intermediary, `client.address` SHOULD represent the client address behind any intermediaries, for example proxies, if it's available. + +**[8] `client.port`:** When observed from the server side, and when communicating through an intermediary, `client.port` SHOULD represent the client port behind any intermediaries, for example proxies, if it's available. + +**[9] `network.peer.address`:** If a RPC involved multiple network calls (for example retries), the last contacted address SHOULD be used. + +**[10] `rpc.request.metadata.`:** Instrumentations SHOULD require an explicit configuration of which metadata values are to be captured. +Including all request metadata values can be a security risk - explicit configuration helps avoid leaking sensitive information. + +For example, a property `my-custom-key` with value `["1.2.3.4", "1.2.3.5"]` SHOULD be recorded as +`rpc.request.metadata.my-custom-key` attribute with value `["1.2.3.4", "1.2.3.5"]` + +**[11] `rpc.response.metadata.`:** Instrumentations SHOULD require an explicit configuration of which metadata values are to be captured. +Including all response metadata values can be a security risk - explicit configuration helps avoid leaking sensitive information. + +For example, a property `my-custom-key` with value `["attribute_value"]` SHOULD be recorded as +the `rpc.response.metadata.my-custom-key` attribute with value `["attribute_value"]` + +The following attributes can be important for making sampling decisions +and SHOULD be provided **at span creation time** (if provided at all): + +* [`rpc.method`](/docs/registry/attributes/rpc.md) +* [`server.address`](/docs/registry/attributes/server.md) +* [`server.port`](/docs/registry/attributes/server.md) + +--- + +`error.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. + +| Value | Description | Stability | +| --- | --- | --- | +| `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + + + + + +## Metrics + +Dubbo instrumentations SHOULD collect metrics according to the general +[Semantic Conventions for RPC Metrics](/docs/rpc/rpc-metrics.md). + +`rpc.system.name` MUST be set to `"dubbo"`. + +[DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status diff --git a/model/rpc/spans.yaml b/model/rpc/spans.yaml index 3ae0c5a55b..db63bed2bc 100644 --- a/model/rpc/spans.yaml +++ b/model/rpc/spans.yaml @@ -306,3 +306,122 @@ groups: All JSON RPC error codes SHOULD be considered errors. requirement_level: conditionally_required: when available + + - id: span.rpc.dubbo.call.client + type: span + stability: development + brief: This span represents an outgoing Remote Procedure Call (RPC). + note: | + `rpc.system.name` MUST be set to `"dubbo"` and SHOULD be provided **at span creation time.** + + **Span name:** refer to the [Span Name](/docs/rpc/rpc-spans.md#name) section. + + **Span kind** MUST be `CLIENT`. + + **Span status** Refer to the [Recording Errors](/docs/general/recording-errors.md) + document for details on how to record span status. See also `rpc.response.status_code` attribute + for the details on which values classify as errors. + extends: rpc + span_kind: client + attributes: + - ref: rpc.method + requirement_level: required + - ref: rpc.response.status_code + requirement_level: required + brief: > + The string representation of the Dubbo response status code returned by the server or generated by the client. + examples: ['OK', 'DEADLINE_EXCEEDED', 'SERVER_ERROR'] + note: | + All status codes except `OK` SHOULD be considered errors. + + Status codes reference: + + - Dubbo2: [Dubbo2 Protocol Status Codes](https://dubbo.apache.org/en/overview/reference/protocols/tcp/#protocol-specification) + - Dubbo3 Triple protocol: [Triple Protocol Error Codes](https://dubbo.apache.org/en/overview/reference/protocols/triple-spec/#311-request) + - ref: server.address + requirement_level: + conditionally_required: If available. + examples: ['192.168.1.100', 'api.example.com'] + note: | + Instrumentations SHOULD populate `server.address` (along with `server.port`) + based on the configuration used when creating the Dubbo client and + SHOULD NOT use actual network-level connection information for this purpose + to ensure low cardinality. + + The Dubbo registry address SHOULD NOT be used as `server.address`. Instead, use + the address of the actual server being called. + + - Given the target URL `dubbo://192.168.1.100:20880/com.example.DemoService`, expected attributes: + - `server.address`: `"192.168.1.100"` + - `server.port`: `20880` + - Given the target URL `tri://api.example.com:50051/com.example.GreeterService`, expected attributes: + - `server.address`: `"api.example.com"` + - `server.port`: `50051` + - Given the target URL `tri://api.example.com/com.example.GreeterService` (port not specified), expected attributes: + - `server.address`: `"api.example.com"` + - `server.port`: not set + + When the address is an IP address, instrumentations SHOULD NOT do a + reverse proxy lookup to obtain a DNS name and SHOULD set `server.address` + to the IP address provided. + - ref: server.port + requirement_level: + conditionally_required: if `server.address` is set and if the port is supported by the network transport used for communication. + examples: [20880, 50051] + note: > + See the `server.address` for details on parsing the target string. + - ref: rpc.request.metadata + requirement_level: opt_in + - ref: rpc.response.metadata + requirement_level: opt_in + + - id: span.rpc.dubbo.call.server + type: span + stability: development + extends: rpc.server + span_kind: server + brief: This span represents an incoming Remote Procedure Call (RPC). + note: | + `rpc.system.name` MUST be set to `"dubbo"` and SHOULD be provided **at span creation time.** + + **Span name:** refer to the [Span Name](/docs/rpc/rpc-spans.md#name) section. + + **Span kind** MUST be `SERVER`. + + **Span status** Refer to the [Recording Errors](/docs/general/recording-errors.md) + document for details on how to record span status. See also `rpc.response.status_code` attribute + for the details on which values classify as errors. + attributes: + - ref: rpc.response.status_code + requirement_level: required + brief: > + The string representation of the Dubbo response status code returned by the server. + examples: ['OK', 'SERVER_ERROR', 'SERVER_THREADPOOL_EXHAUSTED_ERROR'] + note: | + For Dubbo2, the following status codes SHOULD be considered errors: + + - `SERVER_ERROR` + - `SERVER_THREADPOOL_EXHAUSTED_ERROR` + - `SERVER_TIMEOUT` + - `SERVICE_ERROR` + + For Dubbo3 Triple protocol, the following status codes SHOULD be considered errors: + + - `DATA_LOSS` + - `DEADLINE_EXCEEDED` + - `INTERNAL` + - `UNAVAILABLE` + - `UNIMPLEMENTED` + - `UNKNOWN` + + Status codes reference: + + - Dubbo2: [Dubbo2 Protocol Status Codes](https://dubbo.apache.org/en/overview/reference/protocols/tcp/#protocol-specification) + - Dubbo3 Triple protocol: [Triple Protocol Error Codes](https://dubbo.apache.org/en/overview/reference/protocols/triple-spec/#311-request) + - ref: server.port + requirement_level: + conditionally_required: if `server.address` is set and if the port is supported by the network transport used for communication. + - ref: rpc.request.metadata + requirement_level: opt_in + - ref: rpc.response.metadata + requirement_level: opt_in