open-telemetry / open-telemetry/opentelemetry-cpp

Proposal: Include semantic convention attribute types in generated C++ SDK headers

Open
#3,808 4 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

discuss do-not-stale triage/accepted
Dominant language
C++
Stars
1.4k
Forks
632
Avg merge
1d 13h
Merged PRs (30d)
75

Description

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
  1. Keep the current ResourceAttributes API as-is for legacy/backward-compatible usage (planned for eventual deprecation).
  2. 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.
  3. 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.
  4. 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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the semantic-convention source YAML/template files and the existing ResourceAttributes and Resource::Create APIs described in the issue. Compare the proposed typed-key and migration design with the current generated headers. Done would require an agreed scope and implementation plan or PoC; no specific test is named.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
api
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.