Attributes guide

August 4, 2026 ยท View on GitHub

Status: Draft

This document consolidates project decisions and guidance on attributes: naming, placement, cardinality, normalization, and lifecycle.

It complements:

Attribute categories

Attributes fall into three categories.

1) Resource attributes

Describe the producing service and runtime environment.

  • MUST be attached at the resource level
  • MUST NOT be duplicated on every signal
  • SHOULD reuse upstream semantic conventions (service.*, host.*, process.*, container.*)

2) Entity attributes

Identify stable in-process entities (pipelines, nodes, channels, runtime threads).

  • MUST be attached/translated as scope attributes in OTLP exports
  • MUST NOT be duplicated on every signal
  • MUST be stable for the lifetime of the entity
  • MUST be bounded and known at entity creation time
  • MUST be the foundation of metric set identity for core system telemetry

3) Signal-specific attributes

Provide additional bounded context needed to interpret a measurement or event occurrence.

  • MAY be used when required for interpretation
  • MUST be bounded and documented
  • MUST remain meaningful under aggregation (metrics) and filtering (events)

Naming and namespaces

Reuse upstream first

  • Reuse existing OpenTelemetry semantic attributes whenever possible.
  • Do not redefine upstream attributes with different meaning.

Project-defined namespace

Project-defined entity attributes MUST be namespaced to avoid collisions with upstream conventions.

Policy:

  • Use otelcol.* for project-defined attributes.
  • Do not introduce new un-prefixed top-level namespaces for custom entities.

Closed sets (enums)

When an attribute represents a categorical dimension:

  • The value set MUST be a documented closed set.
  • Values MUST be lowercase and stable.
  • Avoid synonyms that fragment cardinality (fail vs error vs failed).

Adding enum values for stable telemetry follows the compatibility rules in stability-compatibility-guide.md.

Placement rules

  • Resource attributes belong on the resource attributes.
  • Entity attributes belong on the scope attributes.
  • Signal-specific attributes belong only where they apply, and must be bounded.

Do not duplicate information:

  • If a value is already present as an entity attribute, do not repeat it as a signal-specific attribute.
  • Prefer a single canonical key.

How the layers are rendered

The self-telemetry pipeline emits each category on its correct OpenTelemetry layer for every exported signal - both metrics and logs (see issue #3161). The mapping is signal-independent:

CategoryOTLP metrics and logsAdmin Prometheus metrics
ResourceResource attributestarget_info gauge labels
EntityInstrumentation scope attributesotel_scope_* series labels
Signal-specificPoint or record attributesInline point labels

Notes:

  • Resource attributes are produced by the detectors listed in engine.telemetry.detectors (default service_instance, env, service_name); host, os, process, container, and k8s are opt-in, and an unrecognized detector name fails engine startup. Precedence is explicitly configured engine.telemetry.resource attributes > detectors > the build-info defaults for service.name/service.version.
  • The opt-in process detector emits process.command_args (the full command line), which can include secrets passed as arguments. Enable it only where that is acceptable.
  • The same resolved resource map feeds every consumer: the native OTLP metric and log resource encoders and the admin target_info gauge - so resource identity is consistent across metrics, logs, and the admin endpoint.
  • Entity identity is resolved from the telemetry registry once per entity and attached as InstrumentationScope.attributes for both metrics and logs (logs carry entity keys via their LogContext). On the admin Prometheus endpoint the same entity attributes are rendered as otel_scope_* labels per the OpenTelemetry-to-Prometheus specification; the reserved keys otel_scope_name, otel_scope_version, and otel_scope_schema_url are not overridden.
  • Engine-global signals (e.g. the memory_rss metric) carry no scope attributes; their identity comes entirely from the Resource layer.
  • Metric sets support bounded enum attributes on the signal-specific data-point layer. See Item Attributes for Metrics.

Core rule

Attributes attached to core system metrics MUST have bounded cardinality.

Before adding an attribute, ask:

  • If I aggregate across this attribute, does the result still make sense?
  • Is the value space bounded and known at entity creation time?

If not, the attribute is mis-modeled for core system metrics.

Prohibited by default in core system metrics

The following are prohibited as metric attributes unless explicitly approved and normalized:

  • user_id, session_id, request_id
  • raw URL path, raw query string
  • raw SQL, raw error messages, unbounded file paths
  • unbounded plugin configuration values

Important node: This restriction may be relaxed in the future through an explicit opt-in mechanism, for example to allow controlled propagation of selected attributes from baggage into metrics or logs under well-defined processing rules.

Normalization patterns

When context is useful but high cardinality, normalize:

  • URL path -> route template
  • SQL query -> normalized fingerprint
  • IP address -> prefix or bucket
  • error message -> error class or error type

Errors and exceptions

Error classification

Prefer low-cardinality classification:

  • Use error.type (or an equivalent stable classifier) when applicable.
  • Avoid raw error messages as attributes in stable telemetry.

Exceptions

When recording an actual exception:

Attributes vs event body

This project distinguishes between queryable attributes and potentially large bodies:

  • Put small, queryable fields in attributes.
  • Put large payloads in the body only when strictly required.
  • Do not duplicate the same data in both places.

Checklist

When introducing a new attribute:

  • It is categorized (resource, entity, signal-specific).
  • It reuses upstream semantic attributes when available.
  • If project-defined, it uses the otelcol.* namespace.
  • Cardinality is bounded and documented.
  • For enums, the closed set is documented and stable.
  • It follows security and privacy rules (no sensitive data).
  • If stable, the change follows the compatibility rules.