Repository: open-telemetry/opentelemetry-collector-contrib (Go)

Issue:
[processor/resourcedetection]  stepping should be a string
### Component(s)

processor/resourcedetection

### What happened?

## Description

Same as #29025 but for CPU stepping number (which surprisingly is not a number).

## Steps to Reproduce

See open-telemetry/semantic-conventions/issues/495

## Expected Result

`host.cpu.stepping` should be set to a string

## Actual Result

It is set to an integer

### Collector version

any

### Environment information

## Environment
not relevant


### OpenTelemetry Collector configuration

_No response_

### Log output

_No response_

### Additional context

cc @ChrsMark interested in taking this?


Discussion:
Pinging code owners:
- processor/resourcedetection: @Aneurysm9 @dashpole

See [Adding Labels via Comments](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#adding-labels-via-comments) if you do not have permissions to add labels yourself.
> cc @ChrsMark interested in taking this?

Sure @mx-psi, happy to take it :)



Patch:
diff --git a/.chloggen/fix_cpu_stepping_type.yaml b/.chloggen/fix_cpu_stepping_type.yaml
new file mode 100755
index 0000000000000..537694e413807
--- /dev/null
+++ b/.chloggen/fix_cpu_stepping_type.yaml
@@ -0,0 +1,28 @@
+# Use this changelog template to create an entry for release notes.
+
+# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
+change_type: enhancement
+
+# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
+component: processor/resourcedetection
+
+# A brief description of the change.  Surround your text with quotes ("") if it needs to start with a backtick (`).
+note: Add `processor.resourcedetection.hostCPUSteppingAsString` feature gate to change the type of `host.cpu.stepping` from `int` to `string`.
+
+# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
+issues: [31136]
+
+# (Optional) One or more lines of additional information to render under the primary note.
+# These lines will be padded with 2 spaces and then inserted directly into the document.
+# Use pipe (|) for multiline entries.
+subtext: |
+  This feature gate will graduate to beta in the next release.
+
+# If your change doesn't affect end users or the exported elements of any package,
+# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
+# Optional: The change log or logs in which this entry should be included.
+# e.g. '[user]' or '[user, api]'
+# Include 'user' if the change is relevant to end users.
+# Include 'api' if there is a change to a library API.
+# Default: '[user]'
+change_logs: []
diff --git a/processor/resourcedetectionprocessor/internal/system/internal/metadata/generated_resource.go b/processor/resourcedetectionprocessor/internal/system/internal/metadata/generated_resource.go
index b4470e9364938..ede196ac018b4 100644
--- a/processor/resourcedetectionprocessor/internal/system/internal/metadata/generated_resource.go
+++ b/processor/resourcedetectionprocessor/internal/system/internal/metadata/generated_resource.go
@@ -57,9 +57,9 @@ func (rb *ResourceBuilder) SetHostCPUModelName(val string) {
 }
 
 // SetHostCPUStepping sets provided value as "host.cpu.stepping" attribute.
-func (rb *ResourceBuilder) SetHostCPUStepping(val int64) {
+func (rb *ResourceBuilder) SetHostCPUStepping(val string) {
 	if rb.config.HostCPUStepping.Enabled {
-		rb.res.Attributes().PutInt("host.cpu.stepping", val)
+		rb.res.Attributes().PutStr("host.cpu.stepping", val)
 	}
 }
 
diff --git a/processor/resourcedetectionprocessor/internal/system/internal/metadata/resource_int_version.go b/processor/resourcedetectionprocessor/internal/system/internal/metadata/resource_int_version.go
index be77f0644186e..5864e85bf0062 100644
--- a/processor/resourcedetectionprocessor/internal/system/internal/metadata/resource_int_version.go
+++ b/processor/resourcedetectionprocessor/internal/system/internal/metadata/resource_int_version.go
@@ -16,3 +16,10 @@ func (rb *ResourceBuilder) SetHostCPUModelIDAsInt(val int64) {
 		rb.res.Attributes().PutInt("host.cpu.model.id", val)
 	}
 }
+
+// SetHostCPUSteppingAsInt sets provided value as "host.cpu.stepping" attribute as int.
+func (rb *ResourceBuilder) SetHostCPUSteppingAsInt(val int64) {
+	if rb.config.HostCPUModelID.Enabled {
+		rb.res.Attributes().PutInt("host.cpu.stepping", val)
+	}
+}
diff --git a/processor/resourcedetectionprocessor/internal/system/metadata.yaml b/processor/resourcedetectionprocessor/internal/system/metadata.yaml
index 93de1f2f9d3cb..47ebfd6faa012 100644
--- a/processor/resourcedetectionprocessor/internal/system/metadata.yaml
+++ b/processor/resourcedetectionprocessor/internal/system/metadata.yaml
@@ -49,7 +49,7 @@ resource_attributes:
     enabled: false
   host.cpu.stepping:
     description: The host.cpu.stepping
-    type: int
+    type: string
     enabled: false
   host.cpu.cache.l2.size:
     description: The host.cpu.cache.l2.size
diff --git a/processor/resourcedetectionprocessor/internal/system/system.go b/processor/resourcedetectionprocessor/internal/system/system.go
index 7d46a902fdd3b..a8614584b330b 100644
--- a/processor/resourcedetectionprocessor/internal/system/system.go
+++ b/processor/resourcedetectionprocessor/internal/system/system.go
@@ -32,6 +32,14 @@ var (
 		featuregate.WithRegisterFromVersion("v0.89.0"),
 		featuregate.WithRegisterReferenceURL("https://github.com/open-telemetry/semantic-conventions/issues/495"),
 	)
+	hostCPUSteppingAsStringID          = "processor.resourcedetection.hostCPUSteppingAsString"
+	hostCPUSteppingAsStringFeatureGate = featuregate.GlobalRegistry().MustRegister(
+		hostCPUSteppingAsStringID,
+		featuregate.StageAlpha,
+		featuregate.WithRegisterDescription("Change type of host.cpu.stepping to string."),
+		featuregate.WithRegisterFromVersion("v0.95.0"),
+		featuregate.WithRegisterReferenceURL("https://github.com/open-telemetry/semantic-conventions/issues/664"),
+	)
 )
 
 const (
@@ -232,7 +240,16 @@ func setHostCPUInfo(d *Detector, cpuInfo cpu.InfoStat) error {
 	}
 
 	d.rb.SetHostCPUModelName(cpuInfo.ModelName)
-	d.rb.SetHostCPUStepping(int64(cpuInfo.Stepping))
+	if hostCPUSteppingAsStringFeatureGate.IsEnabled() {
+		d.rb.SetHostCPUStepping(fmt.Sprintf("%d", cpuInfo.Stepping))
+	} else {
+		// https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/31136
+		d.logger.Info("This attribute will change from int to string. Switch now using the feature gate.",
+			zap.String("attribute", "host.cpu.stepping"),
+			zap.String("feature gate", hostCPUSteppingAsStringID),
+		)
+		d.rb.SetHostCPUSteppingAsInt(int64(cpuInfo.Stepping))
+	}
 	d.rb.SetHostCPUCacheL2Size(int64(cpuInfo.CacheSize))
 	return nil
 }


Test patch:
diff --git a/processor/resourcedetectionprocessor/internal/system/internal/metadata/generated_resource_test.go b/processor/resourcedetectionprocessor/internal/system/internal/metadata/generated_resource_test.go
index 2d9e2811c3588..b1ebc3301a862 100644
--- a/processor/resourcedetectionprocessor/internal/system/internal/metadata/generated_resource_test.go
+++ b/processor/resourcedetectionprocessor/internal/system/internal/metadata/generated_resource_test.go
@@ -18,7 +18,7 @@ func TestResourceBuilder(t *testing.T) {
 			rb.SetHostCPUFamily("host.cpu.family-val")
 			rb.SetHostCPUModelID("host.cpu.model.id-val")
 			rb.SetHostCPUModelName("host.cpu.model.name-val")
-			rb.SetHostCPUStepping(17)
+			rb.SetHostCPUStepping("host.cpu.stepping-val")
 			rb.SetHostCPUVendorID("host.cpu.vendor.id-val")
 			rb.SetHostID("host.id-val")
 			rb.SetHostIP([]any{"host.ip-item1", "host.ip-item2"})
@@ -70,7 +70,7 @@ func TestResourceBuilder(t *testing.T) {
 			val, ok = res.Attributes().Get("host.cpu.stepping")
 			assert.Equal(t, test == "all_set", ok)
 			if ok {
-				assert.EqualValues(t, 17, val.Int())
+				assert.EqualValues(t, "host.cpu.stepping-val", val.Str())
 			}
 			val, ok = res.Attributes().Get("host.cpu.vendor.id")
 			assert.Equal(t, test == "all_set", ok)