From 500d07f70ac35a9a7714e8f693df97a8c6ba3fc3 Mon Sep 17 00:00:00 2001 From: Tigran Najaryan Date: Fri, 1 Dec 2023 12:09:08 -0500 Subject: [PATCH] Add service.type experimental convention Contributes to https://github.com/open-telemetry/semantic-conventions/issues/554 Contributes to https://github.com/open-telemetry/semantic-conventions/issues/396 Contributes to https://github.com/open-telemetry/opamp-spec/issues/131 `service.name` Resource attribute is [currently defined](https://github.com/open-telemetry/semantic-conventions/tree/main/docs/resource#service) as the "Logical name of the service". The expectation is that `service.name` will be set by the operator of the service to a value that describes the role of the service in the overall observable set of entities the operator has (within a `service.namespace). Otel Collector [sets](https://github.com/open-telemetry/opentelemetry-collector/blob/7e3e725a2952728560b9f5f71867ad6358b1977f/service/service.go#L276) `service.name` by default to be the name of the executable (e.g. otelcorecol or otelcontribcol). Collector's `service.name` can be overridden by the operator using `service.telemetry.resource` setting of Collector's config file. This is typically expected in any non-trivial infrastructure where the same Collector executable can be used as a locally running agent on a host, as a standalone gateway that serves as an intermediary between agents and the backends, as part of Kubernetes operator, etc. The roles in these cases are sufficiently different to warrant different logical names. However, there is currently no semantic convention for an attribute that specifies the type of a service that may have different logical roles when used in different places in the infrastructure, yet be identically produced, i.e. be the exact same executable. The executable file name to some extent can serve that purpose but nothing prevents different service types from having the same executable file name, it has poor uniqueness guarantees. This [issue](https://github.com/open-telemetry/semantic-conventions/issues/396) talk a bit more about why we would want to have the type of an agent (Otel Collector in our case) to be a well-defined semantic convention. This [issue](https://github.com/open-telemetry/opamp-spec/issues/131) shows how the agent type would be useful in the context of agent management. The issue talks about how it is important to tie agent's own telemetry's Resource to the attributes that identify that agent in the context of the OpAMP protocol. This change adds `service.type` as Recommended, experimental Resource semantic convention. The value is a string in reverse domain notation that uniquely identifies the type of the service, e.g. io.opentelemetry.collector, io.redis, etc. Unlike (service.namespace,service.name,service.instance.id) triplet the (service.namespace,service.type,service.instance.id) triplet is not guaranteed to be globally unique. Note that having a separate `service.type` allows OpAMP if wanted by the operator to manage the same type of agents in a similar way even though their `service.name` values may be different due to different logical roles they have. Another example with NGINX: `service.type` will be set to com.nginx by NGINX developers, while `service.name` is set to "api-gateway" by the operator, denoting the logical role that the particular NGINX deployment serves in this particular system. --- docs/resource/README.md | 3 +++ model/resource/service_experimental.yaml | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/docs/resource/README.md b/docs/resource/README.md index 5a12b18593..39e1a6b0a8 100644 --- a/docs/resource/README.md +++ b/docs/resource/README.md @@ -101,10 +101,13 @@ as specified in the [Resource SDK specification](https://github.com/open-telemet |---|---|---|---|---| | `service.instance.id` | string | The string ID of the service instance. [1] | `my-k8s-pod-deployment-1`; `627cc493-f310-47de-96bd-71410b7dec09` | Recommended | | `service.namespace` | string | A namespace for `service.name`. [2] | `Shop` | Recommended | +| `service.type` | string | The service type in reverse domain name notation. [3] | `io.opentelemetry.collector`; `io.redis`; `org.apache.kafka` | Recommended | **[1]:** MUST be unique for each instance of the same `service.namespace,service.name` pair (in other words `service.namespace,service.name,service.instance.id` triplet MUST be globally unique). The ID helps to distinguish instances of the same service that exist at the same time (e.g. instances of a horizontally scaled service). It is preferable for the ID to be persistent and stay the same for the lifetime of the service instance, however it is acceptable that the ID is ephemeral and changes during important lifetime events for the service (e.g. service restarts). If the service has no inherent unique ID that can be used as the value of this attribute it is recommended to generate a random Version 1 or Version 4 RFC 4122 UUID (services aiming for reproducible UUIDs may also use Version 5, see RFC 4122 for more recommendations). **[2]:** A string value having a meaning that helps to distinguish a group of services, for example the team name that owns a group of services. `service.name` is expected to be unique within the same namespace. If `service.namespace` is not specified in the Resource then `service.name` is expected to be unique for all services that have no explicit namespace defined (so the empty/unspecified namespace is simply one more valid namespace). Zero-length namespace string is assumed equal to unspecified namespace. + +**[3]:** The `service.type` identifies the product that is deployed as the service. The same product may be simultaneously deployed multiple times on the same observable infrastructure. In this case each of these deployments will typically have a distinct `service.name` to help identify the logical role of the particular deployment, however their `service.type` will be the same and will help identify the deployed product. Note: `service.namespace` and `service.name` are not intended to be concatenated for the purpose of forming a single globally unique name for the service. For example the following 2 sets of attributes actually describe 2 different services (despite the fact that the concatenation would result in the same string): diff --git a/model/resource/service_experimental.yaml b/model/resource/service_experimental.yaml index 43c869ee35..e599f84b95 100644 --- a/model/resource/service_experimental.yaml +++ b/model/resource/service_experimental.yaml @@ -35,3 +35,15 @@ groups: (services aiming for reproducible UUIDs may also use Version 5, see RFC 4122 for more recommendations). examples: ["my-k8s-pod-deployment-1", "627cc493-f310-47de-96bd-71410b7dec09"] + - id: type + type: string + brief: > + The service type in reverse domain name notation. + note: > + The `service.type` identifies the product that is deployed as the service. + The same product may be simultaneously deployed multiple times on the + same observable infrastructure. In this case each of these deployments + will typically have a distinct `service.name` to help identify the + logical role of the particular deployment, however their + `service.type` will be the same and will help identify the deployed product. + examples: ["io.opentelemetry.collector", "io.redis", "org.apache.kafka"]