|
| 1 | +<!--- Hugo front matter used to generate the website version of this page: |
| 2 | +linkTitle: Entity Propagation |
| 3 | +---> |
| 4 | + |
| 5 | +# Entity Propagation |
| 6 | + |
| 7 | +**Status**: [Development](../document-status.md) |
| 8 | + |
| 9 | +<details> |
| 10 | +<summary>Table of Contents</summary> |
| 11 | + |
| 12 | +<!-- toc --> |
| 13 | + |
| 14 | +- [Overview](#overview) |
| 15 | +- [Specifying entity information via an environment variable](#specifying-entity-information-via-an-environment-variable) |
| 16 | + * [Format Specification](#format-specification) |
| 17 | + * [Grammar](#grammar) |
| 18 | + * [Examples](#examples) |
| 19 | + * [Parsing Algorithm](#parsing-algorithm) |
| 20 | + * [Character Encoding](#character-encoding) |
| 21 | + * [Validation Requirements](#validation-requirements) |
| 22 | + * [Error Handling](#error-handling) |
| 23 | +- [EnvEntityDetector](#enventitydetector) |
| 24 | + |
| 25 | +<!-- tocstop --> |
| 26 | + |
| 27 | +</details> |
| 28 | + |
| 29 | +## Overview |
| 30 | + |
| 31 | +Entity propagation provides a mechanism to pass entity information across |
| 32 | +process boundaries using environment variables. This allows entities to be |
| 33 | +shared between parent and child processes, similar to how trace context is |
| 34 | +propagated in distributed systems. This approach is particularly useful when |
| 35 | +the outside process knows more about the child entity than the child process |
| 36 | +can discover on its own. |
| 37 | + |
| 38 | +Common scenarios where entity propagation is beneficial include: |
| 39 | + |
| 40 | +- Container orchestration systems where the orchestrator knows container metadata |
| 41 | +- CI/CD pipelines where the build system knows job and environment details |
| 42 | +- Batch processing systems where the scheduler knows task context |
| 43 | +- Command-line tools spawned with specific entity context |
| 44 | + |
| 45 | +Environment variables provide a reliable, cross-platform mechanism for this |
| 46 | +propagation since they are automatically inherited by child processes and |
| 47 | +available during process initialization. |
| 48 | + |
| 49 | +## Specifying entity information via an environment variable |
| 50 | + |
| 51 | +To enable standardized entity propagation across OpenTelemetry implementations, |
| 52 | +this specification defines the `OTEL_ENTITIES` environment variable format and |
| 53 | +processing requirements. |
| 54 | + |
| 55 | +The SDK that has access to environment variables MUST provide |
| 56 | +an `EnvEntityDetector` which will use the `OTEL_ENTITIES` environment variable |
| 57 | +to discover and associate defined entities with the resource. |
| 58 | + |
| 59 | +The `OTEL_ENTITIES` environment variable contains a list of entities in a |
| 60 | +compact format designed for human readability and concise representation. |
| 61 | + |
| 62 | +### Format Specification |
| 63 | + |
| 64 | +Each entity follows this structure: |
| 65 | + |
| 66 | +``` |
| 67 | +type{id_key1=id_value1,id_key2=id_value2}[desc_key1=desc_value1,desc_key2=desc_value2]@schema_url |
| 68 | +``` |
| 69 | + |
| 70 | +Where: |
| 71 | + |
| 72 | +- `type` is the entity type (required, e.g., "service", "host", "container") |
| 73 | +- `{...}` contains identifying attributes as comma-separated key=value pairs (required, at least one pair) |
| 74 | +- `[...]` contains descriptive attributes as comma-separated key=value pairs (optional) |
| 75 | +- `@schema_url` specifies the Schema URL for the entity (optional) |
| 76 | + |
| 77 | +Multiple entities are separated by semicolons (`;`). |
| 78 | + |
| 79 | +### Grammar |
| 80 | + |
| 81 | +``` |
| 82 | +entities := entity (";" entity)* |
| 83 | +entity := type id_attrs desc_attrs? schema_url? | "" |
| 84 | +type := [a-zA-Z][a-zA-Z0-9._-]* |
| 85 | +id_attrs := "{" key_value_list "}" |
| 86 | +desc_attrs := "[" key_value_list "]" |
| 87 | +schema_url := "@" url_string |
| 88 | +key_value_list := key_value ("," key_value)* |
| 89 | +key_value := key "=" value |
| 90 | +key := [a-zA-Z][a-zA-Z0-9._-]* |
| 91 | +value := [^{}[\]@;,=]* |
| 92 | +url_string := [^;]* |
| 93 | +``` |
| 94 | + |
| 95 | +### Examples |
| 96 | + |
| 97 | +```bash |
| 98 | +# Single service entity |
| 99 | +OTEL_ENTITIES="service{service.name=my-app,service.instance.id=instance-1}[service.version=1.0.0]" |
| 100 | + |
| 101 | +# Multiple entities with schema URL |
| 102 | +OTEL_ENTITIES="service{service.name=my-app,service.instance.id=instance-1}[service.version=1.0.0]@https://opentelemetry.io/schemas/1.21.0;host{host.id=host-123}[host.name=web-server-01]" |
| 103 | + |
| 104 | +# Kubernetes pod entity |
| 105 | +OTEL_ENTITIES="k8s.pod{k8s.pod.uid=pod-abc123}[k8s.pod.name=my-pod,k8s.pod.label.app=my-app]" |
| 106 | + |
| 107 | +# Container with host (minimal descriptive attributes) |
| 108 | +OTEL_ENTITIES="container{container.id=cont-456};host{host.id=host-789}[host.name=docker-host]" |
| 109 | + |
| 110 | +# Minimal entity (only required fields) |
| 111 | +OTEL_ENTITIES="service{service.name=minimal-app}" |
| 112 | + |
| 113 | +# Empty strings are allowed (leading, trailing, and consecutive semicolons are ignored) |
| 114 | +OTEL_ENTITIES=";service{service.name=app1};;host{host.id=host-123};" |
| 115 | +``` |
| 116 | + |
| 117 | +### Parsing Algorithm |
| 118 | + |
| 119 | +1. Split the input string by semicolons (`;`) to get individual entity definitions |
| 120 | +2. For each entity definition: |
| 121 | + a. Skip if the entity definition is empty (allows consecutive semicolons and leading/trailing semicolons) |
| 122 | + b. Extract the entity type (everything before the first `{`) |
| 123 | + c. Extract identifying attributes from `{...}` block |
| 124 | + d. Extract descriptive attributes from `[...]` block (if present) |
| 125 | + e. Extract schema URL from `@...` portion (if present) |
| 126 | +3. Parse key-value lists using comma (`,`) as separator and equals (`=`) for assignment |
| 127 | +4. Validate that each entity has a non-empty type and at least one identifying attribute |
| 128 | +5. Create entity objects and associate them with the resource |
| 129 | + |
| 130 | +### Character Encoding |
| 131 | + |
| 132 | +All attribute values MUST be considered strings and characters outside the |
| 133 | +`baggage-octet` range MUST be percent-encoded following the [W3C Baggage](https://www.w3.org/TR/baggage/#header-content) specification. |
| 134 | + |
| 135 | +The reserved characters `{}[]@;,=` MUST be percent-encoded when they appear literally in attribute values: |
| 136 | + |
| 137 | +- `{` → `%7B` |
| 138 | +- `}` → `%7D` |
| 139 | +- `[` → `%5B` |
| 140 | +- `]` → `%5D` |
| 141 | +- `@` → `%40` |
| 142 | +- `;` → `%3B` |
| 143 | +- `,` → `%2C` |
| 144 | +- `=` → `%3D` |
| 145 | + |
| 146 | +**Example:** |
| 147 | + |
| 148 | +```bash |
| 149 | +# Entity with reserved characters in attribute values |
| 150 | +OTEL_ENTITIES="service{service.name=my%2Capp,service.instance.id=inst-1}[config=key%3Dvalue%5Bprod%5D]" |
| 151 | +# Resolves to: service.name="my,app", config="key=value[prod]" |
| 152 | +``` |
| 153 | + |
| 154 | +### Validation Requirements |
| 155 | + |
| 156 | +- Entity type MUST NOT be empty and MUST match the pattern `[a-zA-Z][a-zA-Z0-9._-]*` |
| 157 | +- At least one identifying attribute MUST be present in the `{...}` block |
| 158 | +- Attribute keys MUST NOT be empty and SHOULD follow OpenTelemetry semantic conventions |
| 159 | +- Schema URL, if present, MUST be a valid URI |
| 160 | +- Entity types SHOULD follow existing OpenTelemetry entity naming conventions (e.g., "service", "host", "container", "k8s.pod") |
| 161 | + |
| 162 | +### Error Handling |
| 163 | + |
| 164 | +The SDK SHOULD be resilient to malformed input and follow these error handling rules: |
| 165 | + |
| 166 | +1. **Invalid syntax**: If the environment variable contains invalid syntax, the SDK SHOULD log a warning and ignore the malformed portions while processing valid parts |
| 167 | + |
| 168 | + Example: `OTEL_ENTITIES="service{service.name=app1};invalid{syntax;service{service.name=app2}"` processes the first valid entity and skips the malformed part |
| 169 | + |
| 170 | +2. **Missing required fields**: If an entity is missing required fields (type or identifying attributes), the SDK SHOULD log a warning and skip that entity |
| 171 | + |
| 172 | + Example: `OTEL_ENTITIES="service{};host{host.id=123}"` skips the service entity (no identifying attributes) and processes the host entity |
| 173 | + |
| 174 | +3. **Duplicate entities**: If multiple entities of the same type with identical identifying attributes are defined, the SDK SHOULD use the last occurrence and SHOULD log a warning |
| 175 | + |
| 176 | + Example: `OTEL_ENTITIES="service{service.name=app1}[version=1.0];service{service.name=app1}[version=2.0]"` uses `version=2.0` |
| 177 | + |
| 178 | +4. **Schema URL validation**: If a schema URL is present but invalid, the SDK SHOULD log a warning and ignore the URL while processing the entity |
| 179 | + |
| 180 | + Example: `OTEL_ENTITIES="service{service.name=app1}@invalid-url"` processes the entity but ignores the invalid URL |
| 181 | + |
| 182 | +5. **Conflicting identifying attributes**: If two entities of the same type define different values for the same identifying attribute key, the SDK SHOULD log a warning and preserve only the last entity |
| 183 | + |
| 184 | + Example: `OTEL_ENTITIES="service{service.name=app1};service{service.name=app2}"` creates only service.name=app2 entity |
| 185 | + |
| 186 | +6. **Conflicting descriptive attributes**: If two entities define different values for the same descriptive attribute key, the SDK SHOULD use the value from the last entity definition and SHOULD log a warning. The conflicting attributes SHOULD NOT be recorded for entities other than the last one |
| 187 | + |
| 188 | + Example: `OTEL_ENTITIES="service{service.name=app1}[version=1.0];service{service.name=app2}[version=2.0]"` results in app1 service without version attribute and app2 service with `version=2.0` |
| 189 | + |
| 190 | +## EnvEntityDetector |
| 191 | + |
| 192 | +TODO: fill out |
0 commit comments