|
| 1 | +<!--- Hugo front matter used to generate the website version of this page: |
| 2 | +linkTitle: Entity Events |
| 3 | +weight: 3 |
| 4 | +---> |
| 5 | + |
| 6 | +# Entity Events |
| 7 | + |
| 8 | +**Status**: [Development](../document-status.md) |
| 9 | + |
| 10 | +<details> |
| 11 | +<summary>Table of Contents</summary> |
| 12 | + |
| 13 | +<!-- toc --> |
| 14 | + |
| 15 | +- [Overview](#overview) |
| 16 | +- [When to Use Entity Events](#when-to-use-entity-events) |
| 17 | +- [Entity Events Data Model](#entity-events-data-model) |
| 18 | + * [Entity State Event](#entity-state-event) |
| 19 | + * [Entity Delete Event](#entity-delete-event) |
| 20 | +- [Entity Relationships](#entity-relationships) |
| 21 | + * [Relationship Structure](#relationship-structure) |
| 22 | + * [Standard Relationship Types](#standard-relationship-types) |
| 23 | + * [Relationship Lifecycle](#relationship-lifecycle) |
| 24 | +- [Examples](#examples) |
| 25 | + * [Kubernetes Pod Entity State](#kubernetes-pod-entity-state) |
| 26 | + * [Entity Delete Event](#entity-delete-event-1) |
| 27 | + |
| 28 | +<!-- tocstop --> |
| 29 | + |
| 30 | +</details> |
| 31 | + |
| 32 | +## Overview |
| 33 | + |
| 34 | +Entity events provide a way to communicate entity information as structured log events. |
| 35 | +This approach is complementary to defining entities as part of Resource data (see [Entity Data Model](./data-model.md)). |
| 36 | + |
| 37 | +Entity events are represented as structured events using the OpenTelemetry [Logs Data Model](../logs/data-model.md), |
| 38 | +specifically as [Events](../logs/data-model.md#events) with a defined `EventName` and attribute structure. |
| 39 | + |
| 40 | +## When to Use Entity Events |
| 41 | + |
| 42 | +Entity events SHOULD be used when: |
| 43 | + |
| 44 | +1. **No Associated Telemetry**: The entity has no telemetry signals associated with it, or |
| 45 | + the telemetry is less important than the entity data itself. |
| 46 | + |
| 47 | +2. **Complex Descriptive Information**: Entity descriptive information is too complex for |
| 48 | + simple resource attribute values. The resource attribute values are expected to be simple |
| 49 | + strings, but entity descriptions can contain complex values like maps and arrays |
| 50 | + (e.g., Kubernetes ConfigMap content, complex cloud metadata, nested tags). |
| 51 | + |
| 52 | +3. **Entity Relationships**: The entity information needs to include relationships to other |
| 53 | + entities. Resource data cannot contain relationship information. |
| 54 | + |
| 55 | +4. **Lifecycle Tracking**: There is a need to explicitly track entity lifecycle events |
| 56 | + (creation, state changes, deletion) independently from telemetry signals. |
| 57 | + |
| 58 | +## Entity Events Data Model |
| 59 | + |
| 60 | +Entity events use the OpenTelemetry Logs Data Model with specific conventions for the |
| 61 | +`EventName` and `Attributes` fields. |
| 62 | + |
| 63 | +### Entity State Event |
| 64 | + |
| 65 | +The Entity State Event stores information about the state of an entity at a particular moment in time. |
| 66 | + |
| 67 | +**Event Name**: `entity.state` |
| 68 | + |
| 69 | +**Required Attributes**: |
| 70 | + |
| 71 | +| Attribute | Type | Description | |
| 72 | +| --------- | ---- | ----------- | |
| 73 | +| `entity.type` | string | Defines the type of the entity. MUST not change during the lifetime of the entity. For example: "service", "host", "k8s.pod". | |
| 74 | +| `entity.id` | map<string, AnyValue> | Attributes that identify the entity. MUST not change during the lifetime of the entity. The map MUST contain at least one attribute. Follows OpenTelemetry [attribute definition](../common/README.md#attribute). | |
| 75 | + |
| 76 | +**Optional Attributes**: |
| 77 | + |
| 78 | +| Attribute | Type | Description | |
| 79 | +| --------- | ---- | ----------- | |
| 80 | +| `entity.description` | map<string, AnyValue> | Descriptive (non-identifying) attributes of the entity. MAY change over the lifetime of the entity. These attributes are not part of the entity's identity. Follows [AnyValue](../common/README.md#anyvalue) definition: can contain scalar values, arrays, or nested maps. SHOULD follow OpenTelemetry [semantic conventions](https://github.com/open-telemetry/semantic-conventions) for attributes. | |
| 81 | +| `entity.interval` | int64 (milliseconds) | Defines the reporting period, i.e., how frequently information about this entity is reported via Entity State events even if the entity does not change. The next expected Entity State event for this entity is expected at (Timestamp + Interval) time. Can be used by receivers to infer that a no longer reported entity is gone, even if the Entity Delete event was not observed. | |
| 82 | +| `entity.relationships` | array of map<string, AnyValue> | Array of relationships that this entity has with other entities. See [Entity Relationships](#entity-relationships) for details. | |
| 83 | + |
| 84 | +**Timestamp Field**: |
| 85 | + |
| 86 | +The `Timestamp` field of the LogRecord represents the time when the entity state described |
| 87 | +by this event became effective. This is the time measured by the origin clock. |
| 88 | + |
| 89 | +**State Mutations**: |
| 90 | + |
| 91 | +An entity mutates (changes) when one or more of its descriptive attributes changes, or when |
| 92 | +its relationships change. A new descriptive attribute may be added, an existing descriptive |
| 93 | +attribute may be deleted, or a value of an existing descriptive attribute may be changed. |
| 94 | +All these changes represent valid mutations of an entity over time. When these mutations |
| 95 | +happen, the identity of the entity does not change. |
| 96 | + |
| 97 | +When the entity's state changes, sources SHOULD emit a new Entity State event with a fresh |
| 98 | +timestamp and the complete current state of all fields. |
| 99 | + |
| 100 | +**Periodic Reporting**: |
| 101 | + |
| 102 | +Entity event producers SHOULD periodically emit Entity State events even if the entity does |
| 103 | +not change. In this case, the `entity.type`, `entity.id`, `entity.description`, and |
| 104 | +`entity.relationships` fields will remain the same, but a fresh `Timestamp` will be recorded. |
| 105 | +Producing such events allows the system to be resilient to event losses and serves as a |
| 106 | +liveliness indicator. |
| 107 | + |
| 108 | +### Entity Delete Event |
| 109 | + |
| 110 | +The Entity Delete Event indicates that a particular entity is gone. |
| 111 | + |
| 112 | +**Event Name**: `entity.delete` |
| 113 | + |
| 114 | +**Required Attributes**: |
| 115 | + |
| 116 | +| Attribute | Type | Description | |
| 117 | +| --------- | ---- | ----------- | |
| 118 | +| `entity.type` | string | The type of the entity being deleted. | |
| 119 | +| `entity.id` | map<string, AnyValue> | Attributes that identify the entity being deleted. | |
| 120 | + |
| 121 | +**Optional Attributes**: |
| 122 | + |
| 123 | +| Attribute | Type | Description | |
| 124 | +| --------- | ---- | ----------- | |
| 125 | +| `entity.delete.reason` | string | The reason for entity deletion. Examples: "terminated", "expired", "evicted", "user_requested", "scaled_down". | |
| 126 | + |
| 127 | +**Timestamp Field**: |
| 128 | + |
| 129 | +The `Timestamp` field of the LogRecord represents the time when the entity was deleted, |
| 130 | +measured by the origin clock. |
| 131 | + |
| 132 | +**Delivery Guarantees**: |
| 133 | + |
| 134 | +Transmitting Entity Delete events is not guaranteed when an entity is gone. Recipients of |
| 135 | +entity signals MUST be prepared to handle this situation by expiring entities that are no |
| 136 | +longer seeing Entity State events reported. The expiration mechanism is based on the |
| 137 | +previously reported `entity.interval` field. Recipients can use this value to compute when |
| 138 | +to expect the next Entity State event and, if the event does not arrive in a timely manner |
| 139 | +(plus some slack), consider the entity to be gone even if the Entity Delete event was not observed. |
| 140 | + |
| 141 | +## Entity Relationships |
| 142 | + |
| 143 | +Entity relationships describe how entities are connected to each other. Relationships are |
| 144 | +embedded within Entity State events as an array of relationship descriptors. |
| 145 | + |
| 146 | +### Relationship Structure |
| 147 | + |
| 148 | +Each relationship in the `entity.relationships` array is a map containing: |
| 149 | + |
| 150 | +**Required Fields**: |
| 151 | + |
| 152 | +| Field | Type | Description | |
| 153 | +| ----- | ---- | ----------- | |
| 154 | +| `relationship.type` | string | The type of relationship. Describes the semantic meaning of the relationship (e.g., "scheduled_on", "contains", "depends_on"). See [Standard Relationship Types](#standard-relationship-types). | |
| 155 | +| `entity.type` | string | The type of the target entity. | |
| 156 | +| `entity.id` | map<string, AnyValue> | The identifying attributes of the target entity. | |
| 157 | + |
| 158 | +**Optional Fields**: |
| 159 | + |
| 160 | +| Field | Type | Description | |
| 161 | +| ----- | ---- | ----------- | |
| 162 | +| `attributes` | map<string, AnyValue> | Additional relationship-specific attributes that provide context about the relationship. | |
| 163 | + |
| 164 | +**Relationship Direction**: |
| 165 | + |
| 166 | +Relationships have direction: `source --[type]--> target`, where: |
| 167 | + |
| 168 | +- The **source** is the entity emitting the Entity State event |
| 169 | +- The **target** is referenced in the relationship descriptor |
| 170 | + |
| 171 | +### Standard Relationship Types |
| 172 | + |
| 173 | +The following are recommended relationship types with their semantic meanings: |
| 174 | + |
| 175 | +| Type | Direction | Meaning | Example | |
| 176 | +| ---- | --------- | ------- | ------- | |
| 177 | +| `runs_on` | Logical → Infrastructure | A logical entity runs on infrastructure | Process → Host | |
| 178 | +| `scheduled_on` | Workload → Infrastructure | A workload is scheduled on infrastructure | Pod → Node | |
| 179 | +| `contains` | Parent → Child | A parent entity contains a child entity | Pod → Container | |
| 180 | +| `part_of` | Child → Parent | A child entity is part of a parent | Container → Pod | |
| 181 | +| `depends_on` | Consumer → Dependency | An entity depends on another for functionality | Service → Database | |
| 182 | +| `manages` | Controller → Controlled | An entity manages the lifecycle of another | Deployment → ReplicaSet | |
| 183 | +| `hosts` | Infrastructure → Workload | Infrastructure hosts a workload (reverse of scheduled_on) | Node → Pod | |
| 184 | + |
| 185 | +Custom relationship types MAY be defined to represent domain-specific relationships. |
| 186 | +Semantic conventions MUST define standard relationship types for common entity types. |
| 187 | + |
| 188 | +### Relationship Lifecycle |
| 189 | + |
| 190 | +**Creating Relationships**: |
| 191 | +Emit an Entity State event with the new relationship included in the `entity.relationships` array. |
| 192 | + |
| 193 | +**Updating Relationships**: |
| 194 | +Emit a new Entity State event with the updated `entity.relationships` array reflecting the current state. |
| 195 | + |
| 196 | +**Deleting Relationships**: |
| 197 | +Emit a new Entity State event with the relationship removed from the `entity.relationships` array. |
| 198 | + |
| 199 | +**Implicit Deletion**: |
| 200 | +When an entity is deleted (Entity Delete event is emitted), all relationships where that |
| 201 | +entity is the source are implicitly deleted. Backends SHOULD handle this accordingly. |
| 202 | + |
| 203 | +## Examples |
| 204 | + |
| 205 | +### Kubernetes Pod Entity State |
| 206 | + |
| 207 | +```json |
| 208 | +{ |
| 209 | + "timestamp": "2026-01-12T10:30:00.000000000Z", |
| 210 | + "eventName": "entity.state", |
| 211 | + "resource": { |
| 212 | + "attributes": { |
| 213 | + "k8s.cluster.name": "prod-cluster" |
| 214 | + } |
| 215 | + }, |
| 216 | + "attributes": { |
| 217 | + "entity.type": "k8s.pod", |
| 218 | + "entity.id": { |
| 219 | + "k8s.pod.uid": "abc-123-def-456" |
| 220 | + }, |
| 221 | + "entity.description": { |
| 222 | + "k8s.pod.name": "nginx-deployment-66b6c", |
| 223 | + "k8s.namespace.name": "default", |
| 224 | + "k8s.pod.labels": { |
| 225 | + "app": "nginx", |
| 226 | + "version": "1.21", |
| 227 | + "tier": "frontend" |
| 228 | + }, |
| 229 | + "k8s.pod.phase": "Running", |
| 230 | + }, |
| 231 | + "entity.interval": 60000, |
| 232 | + "entity.relationships": [ |
| 233 | + { |
| 234 | + "relationship.type": "scheduled_on", |
| 235 | + "entity.type": "k8s.node", |
| 236 | + "entity.id": { |
| 237 | + "k8s.node.uid": "node-001" |
| 238 | + } |
| 239 | + }, |
| 240 | + { |
| 241 | + "relationship.type": "contains", |
| 242 | + "entity.type": "container", |
| 243 | + "entity.id": { |
| 244 | + "container.id": "container-456" |
| 245 | + } |
| 246 | + }, |
| 247 | + { |
| 248 | + "relationship.type": "contains", |
| 249 | + "entity.type": "container", |
| 250 | + "entity.id": { |
| 251 | + "container.id": "container-789" |
| 252 | + } |
| 253 | + }, |
| 254 | + { |
| 255 | + "relationship.type": "part_of", |
| 256 | + "entity.type": "k8s.replicaset", |
| 257 | + "entity.id": { |
| 258 | + "k8s.replicaset.uid": "rs-456" |
| 259 | + } |
| 260 | + } |
| 261 | + ] |
| 262 | + } |
| 263 | +} |
| 264 | +``` |
| 265 | + |
| 266 | +### Entity Delete Event |
| 267 | + |
| 268 | +When the Pod is terminated: |
| 269 | + |
| 270 | +```json |
| 271 | +{ |
| 272 | + "timestamp": "2026-01-12T11:00:00.000000000Z", |
| 273 | + "eventName": "entity.delete", |
| 274 | + "resource": { |
| 275 | + "attributes": { |
| 276 | + "k8s.cluster.name": "prod-cluster" |
| 277 | + } |
| 278 | + }, |
| 279 | + "attributes": { |
| 280 | + "entity.type": "k8s.pod", |
| 281 | + "entity.id": { |
| 282 | + "k8s.pod.uid": "abc-123-def-456" |
| 283 | + }, |
| 284 | + "entity.delete.reason": "terminated" |
| 285 | + } |
| 286 | +} |
| 287 | +``` |
0 commit comments