Repository: open-telemetry/opentelemetry-go (Go)

Issue:
`host.id` is set to empty value in containerized setups
### Description

The [`resource.WithHostID`](https://pkg.go.dev/go.opentelemetry.io/otel/sdk@v1.16.0/resource#WithHostID) option sets the `host.id` resource attribute to the empty string on (certain) containerized setups. The attribute should be set in accordance to [the specification](https://github.com/open-telemetry/semantic-conventions/blob/c6efa4b2b44f9950b332a46311834e23b85bf979/docs/resource/host.md) which states that `host.id` should be a:

> Unique host ID. For Cloud, this must be the instance_id assigned by the cloud provider. For non-containerized systems, this should be the machine-id. See the table below for the sources to use to determine the machine-id based on operating system.

An empty string is not a unique host ID.

### Environment

- OS: Ubuntu 22.04.2, likely irrelevant
- Architecture: x86_64, likely irrelevant
- Go Version: go1.19, likely irrelevant
- opentelemetry-go version: Tested with v1.16.0

### Steps To Reproduce

Run the binary resulting from the following program:

```go
package main

import (
	"context"
	"fmt"

	"go.opentelemetry.io/otel/sdk/resource"
)

func main() {
	res, err := resource.New(context.Background(),
		resource.WithHostID(),
	)

	if err != nil {
		panic(err)
	}

	fmt.Println(res)
}
```

On any of the following images:
- `alpine`
- `ubuntu`
- `centos`
- a `FROM scratch` image (see open-telemetry/opentelemetry-collector-contrib/issues/24230)

The resulting output is:

```
host.id=
```

### Expected behavior

The `host.id` resource attribute is either not set or set to a value that is specification compliant.

----

cc @mwear. I have not tried to reproduce this on opentelemetry-js but it's likely the issue occurs there as well.



Discussion:
I'll fix this.
I opened #4317. It is a fix for this problem, but may or may not be the fix we're looking for. Take a look at the PR description and we can decide what the right thing to do is.
According to the description it indeed fixes the bug

> The host.id resource attribute is either not set or set to a value that is specification compliant.

However, I think it would be good to open another issue (enhancement) to provide a more meaningful value.



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 770c6250764..15731d8c22b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -36,6 +36,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
 
 - Correctly format log messages from the `go.opentelemetry.io/otel/exporters/zipkin` exporter. (#4143)
 - Log an error for calls to `NewView` in `go.opentelemetry.io/otel/sdk/metric` that have empty criteria. (#4307)
+- Fix `resource.WithHostID()` to not set an empty `host.id`. (#4317)
 
 ## [1.16.0/0.39.0] 2023-05-18
 
diff --git a/sdk/resource/host_id_readfile.go b/sdk/resource/host_id_readfile.go
index f92c6dad0f9..721e3ca6e7d 100644
--- a/sdk/resource/host_id_readfile.go
+++ b/sdk/resource/host_id_readfile.go
@@ -21,7 +21,7 @@ import "os"
 func readFile(filename string) (string, error) {
 	b, err := os.ReadFile(filename)
 	if err != nil {
-		return "", nil
+		return "", err
 	}
 
 	return string(b), nil


Test patch:
diff --git a/sdk/resource/host_id_readfile_test.go b/sdk/resource/host_id_readfile_test.go
new file mode 100644
index 00000000000..f071a05cc0c
--- /dev/null
+++ b/sdk/resource/host_id_readfile_test.go
@@ -0,0 +1,53 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//go:build linux || dragonfly || freebsd || netbsd || openbsd || solaris
+
+package resource
+
+import (
+	"os"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestReadFileExistent(t *testing.T) {
+	fileContents := "foo"
+
+	f, err := os.CreateTemp("", "readfile_")
+	require.NoError(t, err)
+
+	defer os.Remove(f.Name())
+
+	_, err = f.WriteString(fileContents)
+	require.NoError(t, err)
+	require.NoError(t, f.Close())
+
+	result, err := readFile(f.Name())
+	require.NoError(t, err)
+	require.Equal(t, result, fileContents)
+}
+
+func TestReadFileNonExistent(t *testing.T) {
+	// create unique filename
+	f, err := os.CreateTemp("", "readfile_")
+	require.NoError(t, err)
+
+	// make file non-existent
+	require.NoError(t, os.Remove(f.Name()))
+
+	_, err = readFile(f.Name())
+	require.ErrorIs(t, err, os.ErrNotExist)
+}