-
Notifications
You must be signed in to change notification settings - Fork 957
Prometheus attribute conversion should merge values when collisions occur #8236
Copy link
Copy link
Open
Labels
BugSomething isn't workingSomething isn't working
Description
According to the prometheus compatibility spec, when converting attributes, if normalizing creates label conflicts the values should be merged together with a ; delimeter and sorted lexigraphically according to original attribute key name.
We don't do this, instead using a naive "first wins" implementation:
Lines 462 to 524 in 9b602eb
| @SuppressWarnings({"rawtypes", "unchecked"}) | |
| private Labels convertAttributes( | |
| @Nullable Resource resource, | |
| @Nullable InstrumentationScopeInfo scope, | |
| Attributes attributes, | |
| String... additionalAttributes) { | |
| List<AttributeKey<?>> allowedAttributeKeys = | |
| allowedResourceAttributesFilter != null | |
| ? filterAllowedResourceAttributeKeys(resource) | |
| : Collections.emptyList(); | |
| Map<String, String> labelNameToValue = new HashMap<>(); | |
| attributes.forEach( | |
| (key, value) -> | |
| labelNameToValue.put( | |
| convertLabelName(key.getKey()), toLabelValue(key.getType(), value))); | |
| for (int i = 0; i < additionalAttributes.length; i += 2) { | |
| labelNameToValue.putIfAbsent( | |
| requireNonNull(additionalAttributes[i]), additionalAttributes[i + 1]); | |
| } | |
| if (scope != null && otelScopeLabelsEnabled) { | |
| labelNameToValue.putIfAbsent(OTEL_SCOPE_NAME, scope.getName()); | |
| if (scope.getVersion() != null) { | |
| labelNameToValue.putIfAbsent(OTEL_SCOPE_VERSION, scope.getVersion()); | |
| } | |
| String schemaUrl = scope.getSchemaUrl(); | |
| if (schemaUrl != null) { | |
| labelNameToValue.putIfAbsent(OTEL_SCOPE_SCHEMA_URL, schemaUrl); | |
| } | |
| scope | |
| .getAttributes() | |
| .forEach( | |
| (key, value) -> | |
| labelNameToValue.putIfAbsent( | |
| OTEL_SCOPE_ATTRIBUTE_PREFIX + key.getKey(), value.toString())); | |
| } | |
| if (resource != null) { | |
| Attributes resourceAttributes = resource.getAttributes(); | |
| for (AttributeKey attributeKey : allowedAttributeKeys) { | |
| Object attributeValue = resourceAttributes.get(attributeKey); | |
| if (attributeValue != null) { | |
| labelNameToValue.putIfAbsent( | |
| convertLabelName(attributeKey.getKey()), attributeValue.toString()); | |
| } | |
| } | |
| } | |
| String[] names = new String[labelNameToValue.size()]; | |
| String[] values = new String[labelNameToValue.size()]; | |
| int[] pos = new int[] {0}; | |
| labelNameToValue.forEach( | |
| (name, value) -> { | |
| names[pos[0]] = name; | |
| values[pos[0]] = value; | |
| pos[0] += 1; | |
| }); | |
| return Labels.of(names, values); | |
| } |
Found while reviewing open-telemetry/opentelemetry-specification#4963
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
BugSomething isn't workingSomething isn't working