Skip to content

Design doc: attribute constants, discriminator on refinements, enum refinements - #1643

Open
lmolkova wants to merge 5 commits into
open-telemetry:mainfrom
lmolkova:attribute-value-constraints
Open

Design doc: attribute constants, discriminator on refinements, enum refinements#1643
lmolkova wants to merge 5 commits into
open-telemetry:mainfrom
lmolkova:attribute-value-constraints

Conversation

@lmolkova

Copy link
Copy Markdown
Member

Related issues #1617, #803, #479, #520, #1590, #892, #878, #1146, #1623, #329

Examples:

Pinning attribute value to constant when referencing attribute and discriminators

spans:
  - type: gen_ai.inference.client
    kind: client
    discriminator: [gen_ai.provider.name]
    # ...

span_refinements:
  - id: openai.inference.client
    ref: gen_ai.inference.client
    attributes:
      - ref: gen_ai.provider.name
        constant: openai   # can be used independently of `discriminator` on base span definition

Specifying a set of known values on a enum

attributes:
  - key: error.type
    stability: stable
    brief: Describes a class of error the operation ended with.
    type:
      members:
        - id: other
          value: _OTHER
          brief: A fallback error value used when the instrumentation has no custom value.
          stability: stable

spans:
  - type: socket.connect
    attributes:
      - ref: error.type
        brief: Socket error code.
        type:
          members:
            - ref: other                         # explicitly list all you want to apply
            - id: network_down
              brief: The network subsystem is unavailable.
              stability: development
            - id: connection_refused
              brief: The remote host actively refused the connection.
              stability: development
            # ... 14 more

Specifying a set of known values on a string attribute

attributes:
  - key: messaging.operation.name
    type: string
    stability: development
    brief: The system-specific name of the messaging operation.

span_refinements:
  - id: azure.servicebus.producer.create
    ref: messaging.producer.create
    attributes:
      - ref: messaging.operation.name
        brief: Azure Service Bus operation name.
        type:
          members:
            - id: send
              brief: Sends a message to a queue or topic.
              stability: development
            - id: schedule
              brief: Schedules a message for future delivery.
              stability: development

@lmolkova
lmolkova requested a review from a team as a code owner July 27, 2026 05:30
@opentelemetry-pr-dashboard

opentelemetry-pr-dashboard Bot commented Jul 27, 2026

Copy link
Copy Markdown

Pull request dashboard status

Waiting on the author · refreshed 2026-08-08 18:42 UTC

Respond to 1 review item (e.g. link a commit, explain why not, ask a follow-up):

  • Inline threads: 1
Status above doesn't look right?
  • Just replied or pushed? Anything around or after the refresh time above may not be picked up yet — give it a few minutes.
  • Should this be with reviewers? Comment /dashboard route:reviewers to route it to them.
  • Anything wrong — including the routing? Report it with what you expected; it helps us improve the dashboard.

@lmolkova lmolkova changed the title Design doc for attribute constants and discriminator on refinements Design do: attribute constants, discriminator on refinements, enum refinements Jul 27, 2026
@lmolkova
lmolkova requested a review from Copilot July 27, 2026 05:31
@lmolkova lmolkova changed the title Design do: attribute constants, discriminator on refinements, enum refinements Design doc: attribute constants, discriminator on refinements, enum refinements Jul 27, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new Weaver design/spec document describing how to model attribute value constraints directly in schema definitions, instead of relying on repeated prose in semantic convention registries.

Changes:

  • Introduces a proposal for pinning referenced attribute values via constant (phase 1).
  • Proposes refinement identification via discriminator (phase 2).
  • Proposes locally constraining/defining known values via type.members on references (phase 3).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread docs/specs/attribute-value-constraints/attribute_value_constraints.md Outdated
@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.5%. Comparing base (a3fbea8) to head (5854d0d).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@          Coverage Diff          @@
##            main   #1643   +/-   ##
=====================================
  Coverage   81.5%   81.5%           
=====================================
  Files        130     130           
  Lines      11616   11616           
=====================================
  Hits        9475    9475           
  Misses      2141    2141           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Comment on lines +186 to +289
### Proposal: `type.members` on a reference (phase 3)

A reference may restate the attribute's members. Two kinds of entry cover every case in the table above:

- `- ref: <member>` selects a member the definition already has. It inherits the member's properties and may
update the ones a reference is allowed to update.
- `- id: <value>` adds a member the definition does not have, and must carry `brief` and `stability` like any
other public definition.

A reference may do this even when the definition is a plain string — it refines the string into a locally
documented enum. That is safe because a string enum carries string values: the wire type never changes, only the
documentation and what code generation can emit. It is also the honest model for `messaging.operation.name`,
which is a string globally because no global vocabulary exists, and a small known set everywhere it is used:

```yaml
attributes:
- key: messaging.operation.name
type: string
stability: development
brief: The system-specific name of the messaging operation.

span_refinements:
- id: azure.servicebus.producer.create
ref: messaging.producer.create
attributes:
- ref: messaging.operation.name
brief: Azure Service Bus operation name.
type:
members:
- id: send
brief: Sends a message to a queue or topic.
stability: development
- id: schedule
brief: Schedules a message for future delivery.
stability: development
```

When the values already exist in the definition, the entries carry nothing but refs — here the GenAI inference
span narrows the definition to a subset of its members:

```yaml
attributes:
- key: gen_ai.operation.name
stability: development
brief: The name of the operation being performed.
type:
members:
- id: chat
value: chat
brief: Chat completion operation such as OpenAI Chat API.
stability: development
- id: embeddings
value: embeddings
brief: Embeddings operation such as OpenAI Create embeddings API.
stability: development
# ... 14 more

spans:
- type: gen_ai.inference.client
kind: client
attributes:
- ref: gen_ai.operation.name
type:
members:
- ref: chat
- ref: generate_content
- ref: text_completion
```

`error.type` needs the same field for the opposite reason — none of its values exist in the definition. Here is
the .NET socket span from the introduction, with each code described instead of listed in prose:

```yaml
attributes:
- key: error.type
stability: stable
brief: Describes a class of error the operation ended with.
type:
members:
- id: other
value: _OTHER
brief: A fallback error value used when the instrumentation has no custom value.
stability: stable

spans:
- type: socket.connect
attributes:
- ref: error.type
brief: Socket error code.
type:
members:
- ref: other
- id: network_down
brief: The network subsystem is unavailable.
stability: development
- id: connection_refused
brief: The remote host actively refused the connection.
stability: development
# ... 14 more
```

There is no "exclude these members" form: `type.members` on a reference replaces the members of the definition.
A new member added to `gen_ai.operation.name` must **not** silently become part of a refinement's set — someone
has to decide which span types it belongs to.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It would be good to understand how hw.state would be modelled using this design. As That is probs one of the most complex.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

like this

spans:
  - type: gen_ai.inference.client
    kind: client
    discriminator: [gen_ai.provider.name]
    # ...

span_refinements:
  - id: openai.inference.client
    ref: gen_ai.inference.client
    attributes:
      - ref: gen_ai.provider.name
        constant: openai   # can be used independently of `discriminator` on base span definition

Comment on lines +302 to +303
- **Turning enums into standalone named types** shared by several attributes. Unrelated to this proposal; the
fields above work either way.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would standalone types not change the solution for 3?

For instance we could just overwrite the type on the ref to a new type which has the same value type. That new type can either be a refinement (additional members) or a new type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants