Background
Currently, semantic convention attributes generated for OpenTelemetry C++ SDK only include string constants for attribute names, with type information (e.g., string, string[], int, bool) only present in source YAML or template files. This limits the ability of applications and SDK to perform type-based sanity checks for attributes, especially when setting resource or span attributes according to semantic conventions.
Reference: Java Implementation
The Java API provides type-safe semantic convention attributes using [AttributeKey<T>](https://github.com/open-telemetry/opentelemetry-java/blob/main/api/all/src/main/java/io/opentelemetry/api/common/AttributeKey. java).
This approach:
- Exposes a generic, type-safe key with compile-time checks.
- Supplies factory methods for common types and arrays.
- Enables both compile-time and runtime attribute validation.
Example:
AttributeKey<String> kHostName = AttributeKey.stringKey("host.name");
AttributeKey<List<String>> kHostIp = AttributeKey.stringArrayKey("host.ip");
Type-Safe API with Backward Compatibility
Inspired by the Java AttributeKey<T> approach, this proposal introduces a type-safe API for semantic convention attributes, while fully preserving backward compatibility by keeping the existing API unchanged.
Solution: Dual API with Forward-Looking Migration Path
- Keep the current
ResourceAttributes API as-is for legacy/backward-compatible usage (planned for eventual deprecation).
- Introduce a new type-safe API:
- Add a
TypedResourceAttributes class that provides a template method for setting attributes using typed keys.
- Generate new
AttributeKey<T> definitions for each semantic convention attribute, exposing both the attribute name and the expected type at compile time.
- Generate the new keys in a
typed sub-namespace for each semconv group, e.g., semconv::host::typed::kHostIp.
- Update SDK to accept
TypedResourceAttributes directly:
- Modify
Resource::Create() to accept both ResourceAttributes (legacy) and TypedResourceAttributes (new).
- No conversion methods — the new API is the forward path; the old API will eventually be deprecated and removed.
- Custom attributes are easy to define:
- Users can define their own typed attribute keys using the same
AttributeKey<T> pattern.
Example
// Legacy usage (unchanged, but deprecated in future)
ResourceAttributes legacy_attrs;
legacy_attrs.SetAttribute(semconv::host::kHostIp, std::vector<std::string>{"192.168.1.1"});
auto resource = Resource::Create(legacy_attrs); // Still works
// NEW: Type-safe usage (forward-looking)
TypedResourceAttributes attrs;
attrs.Set(semconv::host::typed::kHostIp, std::vector<std::string>{"192.168.1.1"});
attrs.Set(semconv:: host::typed::kHostName, "my-server");
// Compile-time error for wrong type:
// attrs.Set(semconv::host::typed::kHostIp, "192.168.1.1"); // Error!
// Direct usage — no conversion needed
auto resource = Resource::Create(attrs); // NEW: Accepts TypedResourceAttributes
// Custom attributes
constexpr auto kMyCustomAttr = AttributeKey<int64_t>("my.custom.metric", AttributeType::kInt64);
attrs.Set(kMyCustomAttr, 12345);
Generated Semantic Convention Example
namespace semconv::host {
// Legacy (eventually deprecated)
static constexpr const char* kHostIp = "host.ip";
// NEW: Type-safe keys
namespace typed {
constexpr auto kHostIp = AttributeKey<std::vector<std::string>>("host.ip", AttributeType::kStringArray);
constexpr auto kHostName = AttributeKey<std::string>("host.name", AttributeType::kString);
constexpr auto kHostCpuCacheL2Size = AttributeKey<int64_t>("host.cpu.cache.l2.size", AttributeType::kInt64);
}
}
SDK API Update
namespace opentelemetry::sdk::resource {
class Resource {
public:
// Legacy (keep for backward compatibility)
static std::unique_ptr<Resource> Create(const ResourceAttributes& attributes);
// NEW: Forward-looking type-safe API
static std::unique_ptr<Resource> Create(const TypedResourceAttributes& attributes);
};
} // namespace
Benefits
- Backward compatible: All existing code works as-is.
- Compile-time safety: New code cannot set incorrect types for semantic conventions.
- Forward-looking: No conversion methods —
TypedResourceAttributes is the future.
- Clear migration path: Developers can incrementally migrate; old API will be deprecated later.
- Easy custom attributes: Users define their own
AttributeKey<T> for custom attributes.
- Clear discoverability: New
typed namespace for semantic-convention keys.
Migration Strategy
Phase 1 (v1.x): Introduce TypedResourceAttributes and AttributeKey<T>, update Resource::Create() to accept both.
Phase 2 (v1.x+n): Deprecate ResourceAttributes with warnings.
Phase 3 (v2.0): Remove ResourceAttributes entirely; TypedResourceAttributes becomes the standard.
Request
Is the community supportive of this forward-looking approach (aligning with Java's model)? If so, I am willing to contribute a PoC or PR for code generation, examples, and integration.
Previous alternatives considered:
- Generate attribute type enums per constant (
kHostIpType)
- Generate a central registry map at runtime
- Generate metadata structs per attribute
- Conversion methods between old and new APIs (rejected — forward path only)
This proposal prefers a type-safe, Java-like API with a clear forward migration path and eventual removal of the legacy API.
Background
Currently, semantic convention attributes generated for OpenTelemetry C++ SDK only include string constants for attribute names, with type information (e.g., string, string[], int, bool) only present in source YAML or template files. This limits the ability of applications and SDK to perform type-based sanity checks for attributes, especially when setting resource or span attributes according to semantic conventions.
Reference: Java Implementation
The Java API provides type-safe semantic convention attributes using [
AttributeKey<T>](https://github.com/open-telemetry/opentelemetry-java/blob/main/api/all/src/main/java/io/opentelemetry/api/common/AttributeKey. java).This approach:
Example:
Type-Safe API with Backward Compatibility
Inspired by the Java
AttributeKey<T>approach, this proposal introduces a type-safe API for semantic convention attributes, while fully preserving backward compatibility by keeping the existing API unchanged.Solution: Dual API with Forward-Looking Migration Path
ResourceAttributesAPI as-is for legacy/backward-compatible usage (planned for eventual deprecation).TypedResourceAttributesclass that provides a template method for setting attributes using typed keys.AttributeKey<T>definitions for each semantic convention attribute, exposing both the attribute name and the expected type at compile time.typedsub-namespace for each semconv group, e.g.,semconv::host::typed::kHostIp.TypedResourceAttributesdirectly:Resource::Create()to accept bothResourceAttributes(legacy) andTypedResourceAttributes(new).AttributeKey<T>pattern.Example
Generated Semantic Convention Example
SDK API Update
Benefits
TypedResourceAttributesis the future.AttributeKey<T>for custom attributes.typednamespace for semantic-convention keys.Migration Strategy
Phase 1 (v1.x): Introduce
TypedResourceAttributesandAttributeKey<T>, updateResource::Create()to accept both.Phase 2 (v1.x+n): Deprecate
ResourceAttributeswith warnings.Phase 3 (v2.0): Remove
ResourceAttributesentirely;TypedResourceAttributesbecomes the standard.Request
Is the community supportive of this forward-looking approach (aligning with Java's model)? If so, I am willing to contribute a PoC or PR for code generation, examples, and integration.
Previous alternatives considered:
kHostIpType)This proposal prefers a type-safe, Java-like API with a clear forward migration path and eventual removal of the legacy API.