Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal for flattening attributes from OTLP messages #21

Merged
merged 11 commits into from
Aug 17, 2022
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 197 additions & 0 deletions specification/common/attribute-precedence.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
# Attribute Precedence on transformation to non-OTLP formats
pirgeo marked this conversation as resolved.
Show resolved Hide resolved
joaopgrassi marked this conversation as resolved.
Show resolved Hide resolved

pirgeo marked this conversation as resolved.
Show resolved Hide resolved
<details>
<summary>Table of Contents</summary>

<!-- toc -->

- [Attribute Precedence on transformation to non-OTLP formats](#attribute-precedence-on-transformation-to-non-otlp-formats)
pirgeo marked this conversation as resolved.
Show resolved Hide resolved
- [Overview](#overview)
- [Attribute hierarchy in the OTLP message](#attribute-hierarchy-in-the-otlp-message)
pirgeo marked this conversation as resolved.
Show resolved Hide resolved
- [Precedence per Signal](#precedence-per-signal)
- [Traces](#traces)
- [Span Events](#span-events)
- [Span links](#span-links)
- [Metrics](#metrics)
- [Metric exemplars](#metric-exemplars)
- [Logs](#logs)
- [Considerations](#considerations)
- [Example](#example)
- [Useful links](#useful-links)

<!-- tocstop -->

</details>

## Overview

This document provides supplementary guidelines for the attribute precedence
that exporters should follow when translating from the hierarchical OTLP format
joaopgrassi marked this conversation as resolved.
Show resolved Hide resolved
to non-hierarchical formats.

A mapping is required when flattening out attributes from the structured OTLP
format has attributes at different levels (e.g., Resource attributes,
pirgeo marked this conversation as resolved.
Show resolved Hide resolved
InstrumentationLibraryScope attributes, Attributes on Spans/Metrics/Logs) to a
pirgeo marked this conversation as resolved.
Show resolved Hide resolved
non-hierarchical representation (e.g., OpenMetrics labels).
pirgeo marked this conversation as resolved.
Show resolved Hide resolved
In the case of OpenMetrics, the set of labels is completely flat and must have
unique labels only
(https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#labelset).
Since OpenTelemetry allows for different levels of attributes, it is feasible
pirgeo marked this conversation as resolved.
Show resolved Hide resolved
that the same attribute appears multiple times on different levels.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewers upstream might point out that the current semantic conventions always define attributes to either be on the resource OR the telemetry signal. It might be worth pointing out in the PR description that this also covers custom attributes, which might appear anywhere.


This document aims to provide guidance around consistently transforming
pirgeo marked this conversation as resolved.
Show resolved Hide resolved
OpenTelemetry attributes to flat sets.

## Attribute hierarchy in the OTLP message

Since the OTLP format is a hierarchical format, there is an inherent order in
the attributes.
In this document,
[Resource](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/sdk.md)
attributes are considered to be at the top of the hierarchy, since they are the
most general attributes.
Attributes on individual Spans/ Metric data points/Logs are at the bottom of the
hierarchy, as they are most specialized and only apply to a subset of all data.

**A more specialized attribute that shares an attribute key with more general
attribute will take precedence.**
pirgeo marked this conversation as resolved.
Show resolved Hide resolved

Therefore, more specialized attributes will overwrite more general ones.
pirgeo marked this conversation as resolved.
Show resolved Hide resolved
In some cases it might be desirable to overwrite an attribute like this.
joaopgrassi marked this conversation as resolved.
Show resolved Hide resolved
pirgeo marked this conversation as resolved.
Show resolved Hide resolved
<!-- TODO example -->

When de-normalizing the structured OTLP message to a flat set of key-value
pirgeo marked this conversation as resolved.
Show resolved Hide resolved
pairs, attributes that are present at Resource and InstrumentationLibraryScope
pirgeo marked this conversation as resolved.
Show resolved Hide resolved
level will be duplicated for each Span/Metric data point/Log.
joaopgrassi marked this conversation as resolved.
Show resolved Hide resolved

## Precedence per Signal

Below, the precedence for each of the signals is spelled out explicitly.
Some attributes (e.g., Span Link attributes) should only be used when flattening
joaopgrassi marked this conversation as resolved.
Show resolved Hide resolved
out attributes to transform the respective concept (Span Link attributes should
not be added when transforming attributes on spans, for example).

`A > B` denotes that the attribute on `A` will overwrite the attribute on `B`
pirgeo marked this conversation as resolved.
Show resolved Hide resolved
if the keys clash.

### Traces

```
Span.attributes > ScopeSpans.scope.attributes > ResourceSpans.resource.attributes
```

#### Span Events

```
Span.events.attributes > Span.attributes > ScopeSpans.scope.attributes > ResourceSpans.resource.attributes
```

#### Span links

```
Span.links.attributes > Span.attributes > ScopeSpans.scope.attributes > ResourceSpans.resource.attributes
joaopgrassi marked this conversation as resolved.
Show resolved Hide resolved
```

### Metrics

Metrics are different from Spans and LogRecords, as each Metric has a data field
which can contain one or more data points.
Each data point has a set of attributes, which need to be considered
independently.

```
Metric.data.data_points.attributes > ScopeMetrics.scope.attributes > ResourceMetrics.resource.attributes
```

#### Metric exemplars

```
Metric.data.data_points.exemplars.filtered_attributes > Metric.data.data_points.attributes > ScopeMetrics.scope.attributes > ResourceMetrics.resource.attributes
joaopgrassi marked this conversation as resolved.
Show resolved Hide resolved
```

### Logs

```
LogRecord.log_records.attributes > ScopeLogs.scope.attributes > ResourceLogs.resource.attributes
```

pirgeo marked this conversation as resolved.
Show resolved Hide resolved
## Considerations

Note that this precedence is a strong suggestion, not a requirement.
Code that transforms attributes should follow this mode of flattening, but might
pirgeo marked this conversation as resolved.
Show resolved Hide resolved
diverge if they have a reason to do so.
Furthermore, exporters can apply clash prevention, e.g., by prefixing all
Resource attributes with `resource.`.
pirgeo marked this conversation as resolved.
Show resolved Hide resolved
Note that even then, a Span/Metric data point/LogRecord attribute can overwrite
the resource attribute `attribute_name`, if it is called
`resource.attribute_name`.
Therefore, extra care needs to be taken when prefixing attributes.

## Example

De-duplication can be thought of as a map with unique keys to which the
joaopgrassi marked this conversation as resolved.
Show resolved Hide resolved
attributes are added, from most general to most specialized.
First, the resource attributes are added, then the InstrumentationLibraryScope
attributes, which overwrite the resource attributes if they share a key.
Then the attributes on the Span/Metric data point/LogRecord are added, which
again overwrite keys that are already present.
The final set of key-value pairs are all the pairs in the map.

This YAML-like representation of a theoretical OTLP message has attributes
pirgeo marked this conversation as resolved.
Show resolved Hide resolved
with attribute names that clash on multiple levels.

```yaml
ResourceMetrics:
resource:
attributes:
# key-value pairs (attributes) on the resource
attribute1: resource-attribute-1
attribute2: resource-attribute-2
attribute3: resource-attribute-3
service.name: my-service

scope_metrics:
scope:
attributes:
attribute1: scope-attribute-1
attribute2: scope-attribute-2

metrics:
# there can be multiple data entries here.
data/0:
data_points:
# each data can have multiple data points:
data_point/0:
attributes:
attribute1: data-point-0-attribute-1

data_point/1:
attributes:
attribute1: data-point-1-attribute-1
joaopgrassi marked this conversation as resolved.
Show resolved Hide resolved
```

The structure above contains two data points, thus there will be two data points
in the output.
Their attributes will be:

```yaml
# data point 0
service.name: my-service
attribute1: data-point-0-attribute-1 # only this attribute is different
attribute2: scope-attribute-2
joaopgrassi marked this conversation as resolved.
Show resolved Hide resolved
attribute3: resource-attribute-3

# data point 1
service.name: my-service
attribute1: data-point-1-attribute-1 # only this attribute is different
attribute2: scope-attribute-2
pirgeo marked this conversation as resolved.
Show resolved Hide resolved
attribute3: resource-attribute-3
```

## Useful links

* [Trace Proto](https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/trace/v1/trace.proto)
* [Metrics Proto](https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/metrics/v1/metrics.proto)
* [Logs Proto](https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/logs/v1/logs.proto)
* [Resource Proto](https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/resource/v1/resource.proto)