Skip to content

Commit b5802cb

Browse files
committed
[mdatagen] Replace optional field with availability for attributes
metadata.yaml schema change for attributes: boolean `optional` field replaced with enum `availability` field with the following options: - `default`: always available (replaces `optional: false`) - `conditional`: available when conditions met (replaces `optional: true`) - `opt_in`: requires explicit enablement The `default` option is assumed when availability isn't specified explicitly which is the case for the vast majority use cases. metadata.yaml files upgrade guideline: Replace `optional: true` with `availability: conditional` and `optional: false` with `availability: default` in metadata files.
1 parent 6ccdc89 commit b5802cb

23 files changed

+366
-173
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: breaking
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
7+
component: mdatagen
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: "Replace `optional` field with `availability` field for attributes in metadata schema"
11+
12+
# One or more tracking issues or pull requests related to the change
13+
issues: [13913]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext: |
19+
The `optional` boolean field for attributes has been replaced with an `availability` field that accepts enum values: `default`, `conditional`, or `opt_in`.
20+
- `default`: attribute is always available unless explicitly disabled (replaces `optional: false`)
21+
- `conditional`: attribute is available only when certain conditions are met (replaces `optional: true`)
22+
- `opt_in`: attribute is not available unless explicitly enabled in user config
23+
When `availability` is not specified, it defaults to `default`.
24+
25+
# Optional: The change log or logs in which this entry should be included.
26+
# e.g. '[user]' or '[user, api]'
27+
# Include 'user' if the change is relevant to end users.
28+
# Include 'api' if there is a change to a library API.
29+
# Default: '[user]'
30+
change_logs: [user]

cmd/mdatagen/internal/command.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,14 +221,14 @@ func templatize(tmplFile string, md Metadata) *template.Template {
221221
"attributeInfo": func(an AttributeName) Attribute {
222222
return md.Attributes[an]
223223
},
224-
"getEventOptionalAttributes": func(attrs map[AttributeName]Attribute) []AttributeName {
224+
"getEventConditionalAttributes": func(attrs map[AttributeName]Attribute) []AttributeName {
225225
seen := make(map[AttributeName]bool)
226226
used := make([]AttributeName, 0)
227227

228228
for _, event := range md.Events {
229229
for _, attribute := range event.Attributes {
230230
v, exists := attrs[attribute]
231-
if exists && v.Optional && !seen[attribute] {
231+
if exists && v.IsConditional() && !seen[attribute] {
232232
used = append(used, attribute)
233233
seen[attribute] = true
234234
}
@@ -238,14 +238,14 @@ func templatize(tmplFile string, md Metadata) *template.Template {
238238

239239
return used
240240
},
241-
"getMetricOptionalAttributes": func(attrs map[AttributeName]Attribute) []AttributeName {
241+
"getMetricConditionalAttributes": func(attrs map[AttributeName]Attribute) []AttributeName {
242242
seen := make(map[AttributeName]bool)
243243
used := make([]AttributeName, 0)
244244

245245
for _, event := range md.Metrics {
246246
for _, attribute := range event.Attributes {
247247
v, exists := attrs[attribute]
248-
if exists && v.Optional && !seen[attribute] {
248+
if exists && v.IsConditional() && !seen[attribute] {
249249
used = append(used, attribute)
250250
seen[attribute] = true
251251
}

cmd/mdatagen/internal/command_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ func TestRunContents(t *testing.T) {
188188
wantLogsGenerated: true,
189189
},
190190
{
191-
yml: "with_optional_attribute.yaml",
191+
yml: "with_conditional_attribute.yaml",
192192
wantStatusGenerated: true,
193193
wantReadmeGenerated: true,
194194
wantMetricsGenerated: true,

cmd/mdatagen/internal/loader.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@ import (
1515
"go.opentelemetry.io/collector/confmap/provider/fileprovider"
1616
)
1717

18-
func setAttributesFullName(attrs map[AttributeName]Attribute) {
18+
func setAttributeDefaultFields(attrs map[AttributeName]Attribute) {
1919
for k, v := range attrs {
2020
v.FullName = k
21+
if v.Availability == "" {
22+
v.Availability = AttributeAvailabilityDefault
23+
}
2124
attrs[k] = v
2225
}
2326
}
@@ -61,8 +64,8 @@ func LoadMetadata(filePath string) (Metadata, error) {
6164
return md, err
6265
}
6366

64-
setAttributesFullName(md.Attributes)
65-
setAttributesFullName(md.ResourceAttributes)
67+
setAttributeDefaultFields(md.Attributes)
68+
setAttributeDefaultFields(md.ResourceAttributes)
6669

6770
return md, nil
6871
}

cmd/mdatagen/internal/loader_test.go

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ func TestLoadMetadata(t *testing.T) {
7474
Type: ValueType{
7575
ValueType: pcommon.ValueTypeStr,
7676
},
77-
FullName: "string.resource.attr",
77+
FullName: "string.resource.attr",
78+
Availability: AttributeAvailabilityDefault,
7879
},
7980
"string.enum.resource.attr": {
8081
Description: "Resource attribute with a known set of string values.",
@@ -83,31 +84,35 @@ func TestLoadMetadata(t *testing.T) {
8384
Type: ValueType{
8485
ValueType: pcommon.ValueTypeStr,
8586
},
86-
FullName: "string.enum.resource.attr",
87+
FullName: "string.enum.resource.attr",
88+
Availability: AttributeAvailabilityDefault,
8789
},
8890
"optional.resource.attr": {
8991
Description: "Explicitly disabled ResourceAttribute.",
9092
Enabled: false,
9193
Type: ValueType{
9294
ValueType: pcommon.ValueTypeStr,
9395
},
94-
FullName: "optional.resource.attr",
96+
FullName: "optional.resource.attr",
97+
Availability: AttributeAvailabilityDefault,
9598
},
9699
"slice.resource.attr": {
97100
Description: "Resource attribute with a slice value.",
98101
Enabled: true,
99102
Type: ValueType{
100103
ValueType: pcommon.ValueTypeSlice,
101104
},
102-
FullName: "slice.resource.attr",
105+
FullName: "slice.resource.attr",
106+
Availability: AttributeAvailabilityDefault,
103107
},
104108
"map.resource.attr": {
105109
Description: "Resource attribute with a map value.",
106110
Enabled: true,
107111
Type: ValueType{
108112
ValueType: pcommon.ValueTypeMap,
109113
},
110-
FullName: "map.resource.attr",
114+
FullName: "map.resource.attr",
115+
Availability: AttributeAvailabilityDefault,
111116
},
112117
"string.resource.attr_disable_warning": {
113118
Description: "Resource attribute with any string value.",
@@ -118,7 +123,8 @@ func TestLoadMetadata(t *testing.T) {
118123
Type: ValueType{
119124
ValueType: pcommon.ValueTypeStr,
120125
},
121-
FullName: "string.resource.attr_disable_warning",
126+
FullName: "string.resource.attr_disable_warning",
127+
Availability: AttributeAvailabilityDefault,
122128
},
123129
"string.resource.attr_remove_warning": {
124130
Description: "Resource attribute with any string value.",
@@ -129,7 +135,8 @@ func TestLoadMetadata(t *testing.T) {
129135
Type: ValueType{
130136
ValueType: pcommon.ValueTypeStr,
131137
},
132-
FullName: "string.resource.attr_remove_warning",
138+
FullName: "string.resource.attr_remove_warning",
139+
Availability: AttributeAvailabilityDefault,
133140
},
134141
"string.resource.attr_to_be_removed": {
135142
Description: "Resource attribute with any string value.",
@@ -140,7 +147,8 @@ func TestLoadMetadata(t *testing.T) {
140147
Type: ValueType{
141148
ValueType: pcommon.ValueTypeStr,
142149
},
143-
FullName: "string.resource.attr_to_be_removed",
150+
FullName: "string.resource.attr_to_be_removed",
151+
Availability: AttributeAvailabilityDefault,
144152
},
145153
},
146154

@@ -152,67 +160,82 @@ func TestLoadMetadata(t *testing.T) {
152160
Type: ValueType{
153161
ValueType: pcommon.ValueTypeStr,
154162
},
155-
FullName: "enum_attr",
163+
FullName: "enum_attr",
164+
Availability: AttributeAvailabilityDefault,
156165
},
157166
"string_attr": {
158167
Description: "Attribute with any string value.",
159168
NameOverride: "",
160169
Type: ValueType{
161170
ValueType: pcommon.ValueTypeStr,
162171
},
163-
FullName: "string_attr",
172+
FullName: "string_attr",
173+
Availability: AttributeAvailabilityDefault,
164174
},
165175
"overridden_int_attr": {
166176
Description: "Integer attribute with overridden name.",
167177
NameOverride: "state",
168178
Type: ValueType{
169179
ValueType: pcommon.ValueTypeInt,
170180
},
171-
FullName: "overridden_int_attr",
181+
FullName: "overridden_int_attr",
182+
Availability: AttributeAvailabilityDefault,
172183
},
173184
"boolean_attr": {
174185
Description: "Attribute with a boolean value.",
175186
Type: ValueType{
176187
ValueType: pcommon.ValueTypeBool,
177188
},
178-
FullName: "boolean_attr",
189+
FullName: "boolean_attr",
190+
Availability: AttributeAvailabilityDefault,
179191
},
180192
"boolean_attr2": {
181193
Description: "Another attribute with a boolean value.",
182194
Type: ValueType{
183195
ValueType: pcommon.ValueTypeBool,
184196
},
185-
FullName: "boolean_attr2",
197+
FullName: "boolean_attr2",
198+
Availability: AttributeAvailabilityDefault,
186199
},
187200
"slice_attr": {
188201
Description: "Attribute with a slice value.",
189202
Type: ValueType{
190203
ValueType: pcommon.ValueTypeSlice,
191204
},
192-
FullName: "slice_attr",
205+
FullName: "slice_attr",
206+
Availability: AttributeAvailabilityDefault,
193207
},
194208
"map_attr": {
195209
Description: "Attribute with a map value.",
196210
Type: ValueType{
197211
ValueType: pcommon.ValueTypeMap,
198212
},
199-
FullName: "map_attr",
213+
FullName: "map_attr",
214+
Availability: AttributeAvailabilityDefault,
200215
},
201-
"optional_int_attr": {
202-
Description: "An optional attribute with an integer value",
216+
"conditional_int_attr": {
217+
Description: "A conditional attribute with an integer value",
203218
Type: ValueType{
204219
ValueType: pcommon.ValueTypeInt,
205220
},
206-
FullName: "optional_int_attr",
207-
Optional: true,
221+
FullName: "conditional_int_attr",
222+
Availability: AttributeAvailabilityConditional,
208223
},
209-
"optional_string_attr": {
210-
Description: "An optional attribute with any string value",
224+
"conditional_string_attr": {
225+
Description: "A conditional attribute with any string value",
211226
Type: ValueType{
212227
ValueType: pcommon.ValueTypeStr,
213228
},
214-
FullName: "optional_string_attr",
215-
Optional: true,
229+
FullName: "conditional_string_attr",
230+
Availability: AttributeAvailabilityConditional,
231+
},
232+
"opt_in_bool_attr": {
233+
Description: "An opt-in attribute with a boolean value",
234+
Type: ValueType{
235+
ValueType: pcommon.ValueTypeBool,
236+
},
237+
FullName: "opt_in_bool_attr",
238+
Availability: AttributeAvailabilityOptIn,
216239
},
217240
},
218241
Metrics: map[MetricName]Metric{
@@ -224,7 +247,7 @@ func TestLoadMetadata(t *testing.T) {
224247
Warnings: Warnings{
225248
IfEnabledNotSet: "This metric will be disabled by default soon.",
226249
},
227-
Attributes: []AttributeName{"string_attr", "overridden_int_attr", "enum_attr", "slice_attr", "map_attr", "optional_int_attr", "optional_string_attr"},
250+
Attributes: []AttributeName{"string_attr", "overridden_int_attr", "enum_attr", "slice_attr", "map_attr", "conditional_int_attr", "conditional_string_attr", "opt_in_bool_attr"},
228251
},
229252
Unit: strPtr("s"),
230253
Sum: &Sum{
@@ -240,7 +263,7 @@ func TestLoadMetadata(t *testing.T) {
240263
Warnings: Warnings{
241264
IfConfigured: "This metric is deprecated and will be removed soon.",
242265
},
243-
Attributes: []AttributeName{"string_attr", "boolean_attr", "boolean_attr2", "optional_string_attr"},
266+
Attributes: []AttributeName{"string_attr", "boolean_attr", "boolean_attr2", "conditional_string_attr"},
244267
},
245268
Unit: strPtr("1"),
246269
Gauge: &Gauge{
@@ -301,7 +324,7 @@ func TestLoadMetadata(t *testing.T) {
301324
Warnings: Warnings{
302325
IfEnabledNotSet: "This event will be disabled by default soon.",
303326
},
304-
Attributes: []AttributeName{"string_attr", "overridden_int_attr", "enum_attr", "slice_attr", "map_attr", "optional_int_attr", "optional_string_attr"},
327+
Attributes: []AttributeName{"string_attr", "overridden_int_attr", "enum_attr", "slice_attr", "map_attr", "conditional_int_attr", "conditional_string_attr", "opt_in_bool_attr"},
305328
},
306329
},
307330
"default.event.to_be_renamed": {
@@ -312,7 +335,7 @@ func TestLoadMetadata(t *testing.T) {
312335
Warnings: Warnings{
313336
IfConfigured: "This event is deprecated and will be renamed soon.",
314337
},
315-
Attributes: []AttributeName{"string_attr", "boolean_attr", "boolean_attr2", "optional_string_attr"},
338+
Attributes: []AttributeName{"string_attr", "boolean_attr", "boolean_attr2", "conditional_string_attr"},
316339
},
317340
},
318341
"default.event.to_be_removed": {

cmd/mdatagen/internal/metadata.go

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,18 @@ func validateEvents(events map[EventName]Event, attributes map[AttributeName]Att
212212

213213
type AttributeName string
214214

215+
// AttributeAvailability defines the availability of an attribute.
216+
type AttributeAvailability string
217+
218+
const (
219+
// AttributeAvailabilityDefault means the attribute is always available unless explicitly disabled in user config.
220+
AttributeAvailabilityDefault AttributeAvailability = "default"
221+
// AttributeAvailabilityConditional means the attribute is available only when certain conditions are met.
222+
AttributeAvailabilityConditional AttributeAvailability = "conditional"
223+
// AttributeAvailabilityOptIn means the attribute is not available unless explicitly enabled in user config.
224+
AttributeAvailabilityOptIn AttributeAvailability = "opt_in"
225+
)
226+
215227
func (mn AttributeName) Render() (string, error) {
216228
return FormatIdentifier(string(mn), true)
217229
}
@@ -306,8 +318,31 @@ type Attribute struct {
306318
FullName AttributeName `mapstructure:"-"`
307319
// Warnings that will be shown to user under specified conditions.
308320
Warnings Warnings `mapstructure:"warnings"`
309-
// Optional defines whether the attribute is required.
310-
Optional bool `mapstructure:"optional"`
321+
// Availability defines the availability of the attribute.
322+
Availability AttributeAvailability `mapstructure:"availability"`
323+
}
324+
325+
// IsConditional returns true if the attribute is conditionally available.
326+
func (a Attribute) IsConditional() bool {
327+
return a.Availability == AttributeAvailabilityConditional
328+
}
329+
330+
// UnmarshalText implements the encoding.TextUnmarshaler interface.
331+
func (aa *AttributeAvailability) UnmarshalText(text []byte) error {
332+
switch string(text) {
333+
case "default":
334+
*aa = AttributeAvailabilityDefault
335+
case "conditional":
336+
*aa = AttributeAvailabilityConditional
337+
case "opt_in":
338+
*aa = AttributeAvailabilityOptIn
339+
case "":
340+
// Default value when not specified
341+
*aa = AttributeAvailabilityDefault
342+
default:
343+
return fmt.Errorf("invalid availability %q", string(text))
344+
}
345+
return nil
311346
}
312347

313348
// Name returns actual name of the attribute that is set on the metric after applying NameOverride.
@@ -363,9 +398,9 @@ type Signal struct {
363398
Attributes []AttributeName `mapstructure:"attributes"`
364399
}
365400

366-
func (s Signal) HasOptionalAttribute(attrs map[AttributeName]Attribute) bool {
401+
func (s Signal) HasConditionalAttributes(attrs map[AttributeName]Attribute) bool {
367402
for _, attr := range s.Attributes {
368-
if v, exists := attrs[attr]; exists && v.Optional {
403+
if v, exists := attrs[attr]; exists && v.IsConditional() {
369404
return true
370405
}
371406
}

0 commit comments

Comments
 (0)