How should Open-Telemetry users prevent accidentally creating attributes with matching keys?

126 Views Asked by At

I'm looking at using Open-Telemetry (https://opentelemetry.io/docs/) for a new logging backend, but want to be sure that I (or other users) don't create AttributeKey instances which accidentally duplicate keys from another library. Unfortunately however, I cannot find a discussion on best-practice for choosing key names.

I appears as if Attributes and AttributesBuilder are designed to represent a single-valued map (even though values can be lists, they must have values of the same type), and that a key is unique according to its 'key' and 'type' values.

See: https://javadoc.io/static/io.opentelemetry/opentelemetry-api/1.22.0/io/opentelemetry/api/common/Attributes.html

This creates a risk that eventually two libraries will both create a key such as longKey("user_id"), which feels like it would be bad (especially if the end user cannot modify either library).

https://javadoc.io/static/io.opentelemetry/opentelemetry-api/1.22.0/io/opentelemetry/api/common/AttributeKey.html#longKey(java.lang.String)

To be a "good citizen", should I be prefixing key strings with the the originating package/class name, or similar? If so, is there a doc link to explain this which I can reference in my code?

I'd also like to know if there are syntax limitations on key strings (e.g. not allowing newlines or '/' etc.).

EDIT: Looking at the code (ArrayBackedAttributes & ImmutableKeyValuePairs), I've also noticed an issue whereby the default Attributes implementation seemingly deliberately ignores the "type" when deduplicating.

This means that if two keys with the same key-string but different types exist, one of them will appear to be silently removed from the resulting Attributes instance, rather than replaced (since the get() method uses the AttributeKey#equals() method which does check for type). So it's not even "last one wins" in terms of the external behavior (which is what the code suggests it is trying to achieve).

AttributeKey<String> strKey = AttributeKey.stringKey("foo");
AttributeKey<Boolean> boolKey = AttributeKey.booleanKey("foo");

Attributes attr = Attributes.builder()
    .put(strKey, "String")
    .put(boolKey, true)
    .build();

System.out.println("value=" + attr.get(strKey));

Results in value=null and not value=true !?

Can someone explain the precise expected semantics for "duplicate" keys and how to best avoid them (esp. if writing a shared library)?

1

There are 1 best solutions below

0
On

To be a "good citizen", should I be prefixing key strings with the the originating package/class name, or similar? If so, is there a doc link to explain this which I can reference in my code?

The attribute naming document from the specification says that attribute keys SHOULD use namespacees to avoid collisions. So yes, adding prefix (we call it a namespace), to the attribute is recommended.

I'd also like to know if there are syntax limitations on key strings (e.g. not allowing newlines or '/' etc.).

The same document recommends that attribute names be limited to printable basic latin characters, referencing this link.

As for your last point about attribute key collisions, they should have last win semantics. I've opened this issue in opentelemetry-java to track discuss the issue / fix more.