Dash0 Raises $110M Series B at $1B Valuation

Last updated: May 27, 2026

How Dash0 Processes Kubernetes Object Logs

Detailed description of how Dash0 extracts Kubernetes object identity and owner-reference attributes from logs ingested via the OpenTelemetry k8sobjectsreceiver.

Overview

The OpenTelemetry k8sobjectsreceiver collects Kubernetes objects (Pods, Deployments, Services, Events, and so on) from the Kubernetes API and emits one log record per object. By default, the receiver puts only k8s.namespace.name on the log's resource attributes. The Kubernetes object's identity (its Kind, metadata.uid, metadata.name) lives inside the log body, where Dash0's resource equality does not look.

To make every Kubernetes object discoverable as its own resource entity in Dash0, the ingestion pipeline applies a dedicated processor that:

  • Reads the Kubernetes object identity from the log body.
  • Stamps semconv-compliant per-Kind attributes on each record's resource.
  • Lifts the object's controller owner reference so that workloads correlate across the Kubernetes controller chain.

This offers practical advantages:

  • Per-Kind grouping: Pods land under the k8s.pod resource type, Deployments under k8s.deployment type, Nodes under k8s.node type, and so on, instead of every Kubernetes object falling under the generic k8s.namespace resource type.
  • Owner-chain correlation: A ReplicaSet record carries its parent Deployment's identity. A Job record carries its CronJob's. Use these keys to navigate across the Kubernetes controller graph without joining on log bodies.
  • OpenTelemetry semantic conventions: The emitted attribute keys (k8s.pod.uid, k8s.deployment.name, and so on) match the OpenTelemetry Kubernetes semantic conventions.

What gets extracted

Dash0 only acts on logs that came from the k8sobjectsreceiver: The trigger is the InstrumentationScope.Name being github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sobjectsreceiver. Otherwise, the log is left untouched.

For each candidate log, Dash0 reads the following fields from the body:

Body path (pull mode)Body path (watch mode)Used for
kindobject.kindLook up the semconv per-Kind attributes
apiVersionobject.apiVersionAPI-group validation against the kindmap
metadata.uidobject.metadata.uidk8s.<kind>.uid resource attribute
metadata.nameobject.metadata.namek8s.<kind>.name resource attribute
metadata.namespaceobject.metadata.namespacek8s.namespace.name resource attribute
metadata.ownerReferences[]object.metadata.ownerReferences[]Controller owner enrichment (see below)

Both k8sobjectsreceiver payload shapes are handled. Pull-mode bodies are the raw Kubernetes object. Watch-mode bodies wrap the object inside {type, object}.

Supported Kinds

The processor maps each Kubernetes API resource to its OpenTelemetry semconv attribute prefix. Only Kinds for which the pinned semconv schema defines a <prefix>.name attribute are mapped:

Plural API resourceResource attribute prefixUID stamped
cronjobsk8s.cronjobYes
daemonsetsk8s.daemonsetYes
deploymentsk8s.deploymentYes
horizontalpodautoscalersk8s.hpaYes
jobsk8s.jobYes
namespacesk8s.namespaceYes (see note below)
nodesk8s.nodeYes
persistentvolumeclaimsk8s.persistentvolumeclaimYes
persistentvolumesk8s.persistentvolumeYes
podsk8s.podYes
replicasetsk8s.replicasetYes
replicationcontrollersk8s.replicationcontrollerYes
resourcequotask8s.resourcequotaYes
servicesk8s.serviceYes
statefulsetsk8s.statefulsetYes

The apiGroup is also validated, to avoid spurious scenarios when a CRD, for example, defines a Deployment in a third-party API group such as mycompany.com/v1

Namespace UID

The OpenTelemetry semantic conventions (as of v1.36.0) define k8s.namespace.name as the identifying attribute for a Kubernetes Namespace and do not define a k8s.namespace.uid key. Dash0 still stamps k8s.namespace.uid (using the canonical key) on Namespace records so Namespace resources carry a stable UID identity, the same way every other Kubernetes Kind does. The pseudo-UID k8s.cluster.uid is conventionally derived from the kube-system namespace's UID and is populated by other components such as the OpenTelemetry k8sattributesprocessor or resource detectors, not by this processor.

Records for other Kubernetes resource types

Records for Kubernetes resources without a semconv-defined <prefix>.name attribute (for example configmaps, secrets, ingresses, endpoints, roles, and custom resources) are left exactly where the k8sobjectsreceiver put them.

Owner-reference enrichment

Most Kubernetes objects are controlled by another object. Dash0 reads metadata.ownerReferences[] and, when the controller-marked reference (or the first reference if none is marked controller) points to a Kind in the supported list above, stamps that owner's semconv per-Kind attributes on the same resource.

This is a single-step lift: an owner reference points to the immediate parent, not further up the chain. For example, a Pod's body lists its ReplicaSet as the owner, not the Deployment two levels up. The processor will:

  • Stamp k8s.replicaset.uid and k8s.replicaset.name on the Pod's resource.
  • Not stamp k8s.deployment.* on the Pod's resource (those attributes are unavailable without an additional lookup).
Resource Equality

The owner-reference enrichment in practice is often not necessary because of Dash0's resource equality. But at Dash0, we do like to take all opportunities that present themselves to make your telemetry more meaningful out of the box.

Static pods

Pods created directly on a Node (for example the static pods that run kube-apiserver, etcd, kube-controller-manager, and kube-scheduler on a control-plane Node) declare the Node as their owner. The processor stamps k8s.node.uid and k8s.node.name on those Pods' resources accordingly.

Owner references with mismatched API groups

If an owner reference's apiVersion belongs to a different API group than the semconv entry for the same Kind, the processor skips it. The same rule applies as for the own-Kind path: a Deployment owner reference with apiVersion: mycompany.com/v1 does not produce k8s.deployment.* attributes.

Owner references not in the supported list

Owner references whose Kind has no semconv-defined <prefix>.name attribute (for example a custom Argo Rollout resource) are silently ignored. The Pod or other owned object still carries its own per-Kind attributes; only the owner stamping is skipped.

Edge cases

  • Cluster-scoped objects: Records for cluster-scoped Kubernetes resources (Nodes, Namespaces, PersistentVolumes, and so on) do not carry k8s.namespace.name. The k8s.<kind>.{name,uid} attributes are still stamped on the new resource.
  • Missing object identity: If a record's body is unreadable, missing kind, or missing metadata, the record stays in the source ResourceLogs and no per-Kind attributes are invented.
  • Logs from sources other than k8sobjectsreceiver: Records inside a ScopeLogs whose scope.Name is not github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sobjectsreceiver are not processed as described in this page.

What is preserved on the log record

Source resource attributes are preserved verbatim on the new per-object resource, alongside the per-Kind semconv attributes the processor adds. The moved log records keep all of their original log-record attributes, with one exception: the event.name attribute that the upstream k8sobjectsreceiver stamps in watch mode (holding the verbatim metadata.name of the watched object) is stripped, because it is not a semantically meaningful event identifier. The event.domain attribute, when present, is left alone.

In its place, the moved record's top-level LogRecord.EventName field is set to the stable dotted name k8s.object. This makes the record's identity as a "Kubernetes object snapshot" explicit at the protocol level, independent of the receiver and its mode.

References