diff --git a/.chloggen/add_k8s_ns_phase.yaml b/.chloggen/add_k8s_ns_phase.yaml new file mode 100755 index 000000000..b7813687e --- /dev/null +++ b/.chloggen/add_k8s_ns_phase.yaml @@ -0,0 +1,22 @@ +# Use this changelog template to create an entry for release notes. +# +# 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: k8s + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add k8s.namespace.phase metric along with the respective attribute + +# 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: [1668] + +# (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/attributes-registry/k8s.md b/docs/attributes-registry/k8s.md index 784ab78b5..ab3c706dc 100644 --- a/docs/attributes-registry/k8s.md +++ b/docs/attributes-registry/k8s.md @@ -29,6 +29,7 @@ Kubernetes resource attributes. | `k8s.job.name` | string | The name of the Job. | `opentelemetry` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `k8s.job.uid` | string | The UID of the Job. | `275ecb36-5aa8-4c2a-9c47-d8bb681b9aff` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `k8s.namespace.name` | string | The name of the namespace that the pod is running in. | `default` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `k8s.namespace.phase` | string | The phase of the K8s namespace. [2] | `active`; `terminating` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `k8s.node.name` | string | The name of the Node. | `node-1` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `k8s.node.uid` | string | The UID of the Node. | `1eb3a0c6-0477-4080-a9cb-0cb7db65c6a2` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `k8s.pod.annotation.` | string | The annotation key-value pairs placed on the Pod, the `` being the annotation name, the value being the annotation value. | `k8s.pod.annotation.kubernetes.io/enforce-mountable-secrets=true`; `k8s.pod.annotation.mycompany.io/arch=x64`; `k8s.pod.annotation.data=` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | @@ -65,18 +66,30 @@ Which states: Therefore, UIDs between clusters should be extremely unlikely to conflict. +**[2] `k8s.namespace.phase`:** This attribute aligns with the `phase` field of the +[K8s NamespaceStatus](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#namespacestatus-v1-core) + +--- + +`k8s.namespace.phase` 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 | +|---|---|---| +| `active` | Active namespace phase as described by [K8s API](https://pkg.go.dev/k8s.io/api@v0.31.3/core/v1#NamespacePhase) | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `terminating` | Terminating namespace phase as described by [K8s API](https://pkg.go.dev/k8s.io/api@v0.31.3/core/v1#NamespacePhase) | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + --- `k8s.volume.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 | |---|---|---| -| `configMap` | A [configMap](https://v1-29.docs.kubernetes.io/docs/concepts/storage/volumes/#configmap) volume | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `downwardAPI` | A [downwardAPI](https://v1-29.docs.kubernetes.io/docs/concepts/storage/volumes/#downwardapi) volume | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `emptyDir` | An [emptyDir](https://v1-29.docs.kubernetes.io/docs/concepts/storage/volumes/#emptydir) volume | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `local` | A [local](https://v1-29.docs.kubernetes.io/docs/concepts/storage/volumes/#local) volume | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `persistentVolumeClaim` | A [persistentVolumeClaim](https://v1-29.docs.kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim) volume | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `secret` | A [secret](https://v1-29.docs.kubernetes.io/docs/concepts/storage/volumes/#secret) volume | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `configMap` | A [configMap](https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#configmap) volume | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `downwardAPI` | A [downwardAPI](https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#downwardapi) volume | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `emptyDir` | An [emptyDir](https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#emptydir) volume | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `local` | A [local](https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#local) volume | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `persistentVolumeClaim` | A [persistentVolumeClaim](https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim) volume | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `secret` | A [secret](https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#secret) volume | ![Experimental](https://img.shields.io/badge/-experimental-blue) | ## Deprecated Kubernetes Attributes diff --git a/docs/non-normative/k8s-migration.md b/docs/non-normative/k8s-migration.md index 39e7d464c..022be1d59 100644 --- a/docs/non-normative/k8s-migration.md +++ b/docs/non-normative/k8s-migration.md @@ -51,6 +51,7 @@ and one for disabling the old schema called `semconv.k8s.disableLegacy`. Then: - [K8s DaemonSet metrics](#k8s-daemonset-metrics) - [K8s Job metrics](#k8s-job-metrics) - [K8s Cronjob metrics](#k8s-cronjob-metrics) + - [K8s Namespace metrics](#k8s-namespace-metrics) @@ -234,3 +235,21 @@ The changes in their metric types are the following: | `k8s.cronjob.active_jobs` (type: `gauge`) | `k8s.cronjob.active_jobs` (type: `updowncounter`) | + +### K8s Namespace metrics + +The K8s Namespace metrics implemented by the Collector and specifically the +[k8scluster](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/v0.115.0/receiver/k8sclusterreceiver/documentation.md) +receiver were introduced as semantic conventions in +[#1649](https://github.com/open-telemetry/semantic-conventions/pull/1668) (TODO: replace with SemConv version once +available). + +The changes in their metrics are the following: + + + +| Old (Collector) ![changed](https://img.shields.io/badge/changed-orange?style=flat) | New | +|------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| +| `k8s.namespace.phase` (type: `gauge`), 1 for active and 0 for terminating | `k8s.namespace.phase` (type: `updowncounter`), with the attribute `k8s.namespace.phase` indicating the phase | + + diff --git a/docs/system/k8s-metrics.md b/docs/system/k8s-metrics.md index e95ba7fec..6211d31c6 100644 --- a/docs/system/k8s-metrics.md +++ b/docs/system/k8s-metrics.md @@ -65,6 +65,8 @@ and therefore inherit its attributes, like `k8s.pod.name` and `k8s.pod.uid`. - [Metric: `k8s.job.max_parallel_pods`](#metric-k8sjobmax_parallel_pods) - [CronJob Metrics](#cronjob-metrics) - [Metric: `k8s.cronjob.active_jobs`](#metric-k8scronjobactive_jobs) +- [Namespace Metrics](#namespace-metrics) + - [Metric: `k8s.namespace.phase`](#metric-k8snamespacephase) @@ -1028,5 +1030,48 @@ This metric SHOULD, at a minimum, be reported against a +## Namespace Metrics + +**Description:** Namespace level metrics captured under the namespace `k8s.namespace`. + +### Metric: `k8s.namespace.phase` + +This metric is [recommended][MetricRecommended]. + + + + + + + + +| Name | Instrument Type | Unit (UCUM) | Description | Stability | +| -------- | --------------- | ----------- | -------------- | --------- | +| `k8s.namespace.phase` | UpDownCounter | `{namespace}` | Describes number of K8s namespaces that are currently in a given phase. [1] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + +**[1]:** This metric SHOULD, at a minimum, be reported against a +[`k8s.namespace`](../resource/k8s.md#namespace) resource. + +| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | +|---|---|---|---|---|---| +| [`k8s.namespace.phase`](/docs/attributes-registry/k8s.md) | string | The phase of the K8s namespace. [1] | `active`; `terminating` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + +**[1] `k8s.namespace.phase`:** This attribute aligns with the `phase` field of the +[K8s NamespaceStatus](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#namespacestatus-v1-core) + +--- + +`k8s.namespace.phase` 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 | +|---|---|---| +| `active` | Active namespace phase as described by [K8s API](https://pkg.go.dev/k8s.io/api@v0.31.3/core/v1#NamespacePhase) | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `terminating` | Terminating namespace phase as described by [K8s API](https://pkg.go.dev/k8s.io/api@v0.31.3/core/v1#NamespacePhase) | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + + + + + + [DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status [MetricRecommended]: /docs/general/metric-requirement-level.md#recommended diff --git a/model/k8s/metrics.yaml b/model/k8s/metrics.yaml index 130166227..c091a5e4a 100644 --- a/model/k8s/metrics.yaml +++ b/model/k8s/metrics.yaml @@ -442,3 +442,18 @@ groups: This metric SHOULD, at a minimum, be reported against a [`k8s.cronjob`](../resource/k8s.md#cronjob) resource. + + # k8s.namespace.* metrics + - id: metric.k8s.namespace.phase + type: metric + metric_name: k8s.namespace.phase + stability: experimental + brief: "Describes number of K8s namespaces that are currently in a given phase." + instrument: updowncounter + unit: "{namespace}" + note: | + This metric SHOULD, at a minimum, be reported against a + [`k8s.namespace`](../resource/k8s.md#namespace) resource. + attributes: + - ref: k8s.namespace.phase + requirement_level: required diff --git a/model/k8s/registry.yaml b/model/k8s/registry.yaml index e1e0107fc..c9b639b69 100644 --- a/model/k8s/registry.yaml +++ b/model/k8s/registry.yaml @@ -192,25 +192,43 @@ groups: members: - id: persistent_volume_claim value: 'persistentVolumeClaim' - brief: "A [persistentVolumeClaim](https://v1-29.docs.kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim) volume" + brief: "A [persistentVolumeClaim](https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim) volume" stability: experimental - id: config_map value: 'configMap' - brief: "A [configMap](https://v1-29.docs.kubernetes.io/docs/concepts/storage/volumes/#configmap) volume" + brief: "A [configMap](https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#configmap) volume" stability: experimental - id: downward_api value: 'downwardAPI' - brief: "A [downwardAPI](https://v1-29.docs.kubernetes.io/docs/concepts/storage/volumes/#downwardapi) volume" + brief: "A [downwardAPI](https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#downwardapi) volume" stability: experimental - id: empty_dir value: 'emptyDir' - brief: "An [emptyDir](https://v1-29.docs.kubernetes.io/docs/concepts/storage/volumes/#emptydir) volume" + brief: "An [emptyDir](https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#emptydir) volume" stability: experimental - id: secret value: 'secret' - brief: "A [secret](https://v1-29.docs.kubernetes.io/docs/concepts/storage/volumes/#secret) volume" + brief: "A [secret](https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#secret) volume" stability: experimental - id: local value: 'local' - brief: "A [local](https://v1-29.docs.kubernetes.io/docs/concepts/storage/volumes/#local) volume" + brief: "A [local](https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#local) volume" + stability: experimental + - id: k8s.namespace.phase + stability: experimental + brief: > + The phase of the K8s namespace. + note: | + This attribute aligns with the `phase` field of the + [K8s NamespaceStatus](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#namespacestatus-v1-core) + examples: [ "active", "terminating" ] + type: + members: + - id: active + value: 'active' + brief: "Active namespace phase as described by [K8s API](https://pkg.go.dev/k8s.io/api@v0.31.3/core/v1#NamespacePhase)" + stability: experimental + - id: terminating + value: 'terminating' + brief: "Terminating namespace phase as described by [K8s API](https://pkg.go.dev/k8s.io/api@v0.31.3/core/v1#NamespacePhase)" stability: experimental