add host.id to resource auto-detection (#3812)
* add platform specific hostIDReaders * add WithHostID option to Resource * add changelog entry * Apply suggestions from code review Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com> * linting * combine platform specific readers and tests This allows us to run tests for the BSD, Darwin, and Linux readers on all platforms. * add todo to use assert.AnError after resource.Detect error handling is updated * move HostID test utilities to host_id_test * return assert.AnError from mockHostIDProviderWithError * use assert.ErrorIs Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com> --------- Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com> Co-authored-by: Aaron Clawson <3766680+MadVikingGod@users.noreply.github.com>
This commit is contained in:
parent
1eab60f714
commit
282a47e3d3
|
|
@ -10,6 +10,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|||
|
||||
### Added
|
||||
|
||||
- The `WithHostID` option to `go.opentelemetry.io/otel/sdk/resource`. (#3812)
|
||||
- The `WithoutTimestamps` option to `go.opentelemetry.io/otel/exporters/stdout/stdoutmetric` to sets all timestamps to zero. (#3828)
|
||||
- The new `Exemplar` type is added to `go.opentelemetry.io/otel/sdk/metric/metricdata`.
|
||||
Both the `DataPoint` and `HistogramDataPoint` types from that package have a new field of `Exemplars` containing the sampled exemplars for their timeseries. (#3849)
|
||||
|
|
|
|||
|
|
@ -71,6 +71,11 @@ func WithHost() Option {
|
|||
return WithDetectors(host{})
|
||||
}
|
||||
|
||||
// WithHostID adds host ID information to the configured resource.
|
||||
func WithHostID() Option {
|
||||
return WithDetectors(hostIDDetector{})
|
||||
}
|
||||
|
||||
// WithTelemetrySDK adds TelemetrySDK version info to the configured resource.
|
||||
func WithTelemetrySDK() Option {
|
||||
return WithDetectors(telemetrySDK{})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,142 @@
|
|||
// 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.
|
||||
|
||||
package resource // import "go.opentelemetry.io/otel/sdk/resource"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
|
||||
)
|
||||
|
||||
type hostIDProvider func() (string, error)
|
||||
|
||||
var defaultHostIDProvider hostIDProvider = platformHostIDReader.read
|
||||
|
||||
var hostID = defaultHostIDProvider
|
||||
|
||||
type hostIDReader interface {
|
||||
read() (string, error)
|
||||
}
|
||||
|
||||
type fileReader func(string) (string, error)
|
||||
|
||||
type commandExecutor func(string, ...string) (string, error)
|
||||
|
||||
func readFile(filename string) (string, error) {
|
||||
b, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
// nolint: unused // This is used by the hostReaderBSD, gated by build tags.
|
||||
func execCommand(name string, arg ...string) (string, error) {
|
||||
cmd := exec.Command(name, arg...)
|
||||
b, err := cmd.Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
// hostIDReaderBSD implements hostIDReader.
|
||||
type hostIDReaderBSD struct {
|
||||
execCommand commandExecutor
|
||||
readFile fileReader
|
||||
}
|
||||
|
||||
// read attempts to read the machine-id from /etc/hostid. If not found it will
|
||||
// execute `kenv -q smbios.system.uuid`. If neither location yields an id an
|
||||
// error will be returned.
|
||||
func (r *hostIDReaderBSD) read() (string, error) {
|
||||
if result, err := r.readFile("/etc/hostid"); err == nil {
|
||||
return strings.TrimSpace(result), nil
|
||||
}
|
||||
|
||||
if result, err := r.execCommand("kenv", "-q", "smbios.system.uuid"); err == nil {
|
||||
return strings.TrimSpace(result), nil
|
||||
}
|
||||
|
||||
return "", errors.New("host id not found in: /etc/hostid or kenv")
|
||||
}
|
||||
|
||||
// hostIDReaderDarwin implements hostIDReader.
|
||||
type hostIDReaderDarwin struct {
|
||||
execCommand commandExecutor
|
||||
}
|
||||
|
||||
// read executes `ioreg -rd1 -c "IOPlatformExpertDevice"` and parses host id
|
||||
// from the IOPlatformUUID line. If the command fails or the uuid cannot be
|
||||
// parsed an error will be returned.
|
||||
func (r *hostIDReaderDarwin) read() (string, error) {
|
||||
result, err := r.execCommand("ioreg", "-rd1", "-c", "IOPlatformExpertDevice")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
lines := strings.Split(result, "\n")
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, "IOPlatformUUID") {
|
||||
parts := strings.Split(line, " = ")
|
||||
if len(parts) == 2 {
|
||||
return strings.Trim(parts[1], "\""), nil
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return "", errors.New("could not parse IOPlatformUUID")
|
||||
}
|
||||
|
||||
type hostIDReaderLinux struct {
|
||||
readFile fileReader
|
||||
}
|
||||
|
||||
// read attempts to read the machine-id from /etc/machine-id followed by
|
||||
// /var/lib/dbus/machine-id. If neither location yields an ID an error will
|
||||
// be returned.
|
||||
func (r *hostIDReaderLinux) read() (string, error) {
|
||||
if result, err := r.readFile("/etc/machine-id"); err == nil {
|
||||
return strings.TrimSpace(result), nil
|
||||
}
|
||||
|
||||
if result, err := r.readFile("/var/lib/dbus/machine-id"); err == nil {
|
||||
return strings.TrimSpace(result), nil
|
||||
}
|
||||
|
||||
return "", errors.New("host id not found in: /etc/machine-id or /var/lib/dbus/machine-id")
|
||||
}
|
||||
|
||||
type hostIDDetector struct{}
|
||||
|
||||
// Detect returns a *Resource containing the platform specific host id.
|
||||
func (hostIDDetector) Detect(ctx context.Context) (*Resource, error) {
|
||||
hostID, err := hostID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewWithAttributes(
|
||||
semconv.SchemaURL,
|
||||
semconv.HostID(hostID),
|
||||
), nil
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// 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 dragonfly || freebsd || netbsd || openbsd || solaris
|
||||
// +build dragonfly freebsd netbsd openbsd solaris
|
||||
|
||||
package resource // import "go.opentelemetry.io/otel/sdk/resource"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var platformHostIDReader hostIDReader = &hostIDReaderBSD{
|
||||
execCommand: execCommand,
|
||||
readFile: readFile,
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// 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.
|
||||
|
||||
package resource // import "go.opentelemetry.io/otel/sdk/resource"
|
||||
|
||||
var platformHostIDReader hostIDReader = &hostIDReaderDarwin{
|
||||
execCommand: execCommand,
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// 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.
|
||||
|
||||
package resource_test
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
)
|
||||
|
||||
func mockHostIDProvider() {
|
||||
resource.SetHostIDProvider(
|
||||
func() (string, error) { return "f2c668b579780554f70f72a063dc0864", nil },
|
||||
)
|
||||
}
|
||||
|
||||
func mockHostIDProviderWithError() {
|
||||
resource.SetHostIDProvider(
|
||||
func() (string, error) { return "", assert.AnError },
|
||||
)
|
||||
}
|
||||
|
||||
func restoreHostIDProvider() {
|
||||
resource.SetDefaultHostIDProvider()
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// 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
|
||||
// +build linux
|
||||
|
||||
package resource // import "go.opentelemetry.io/otel/sdk/resource"
|
||||
|
||||
var platformHostIDReader hostIDReader = &hostIDReaderLinux{
|
||||
readFile: readFile,
|
||||
}
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
// 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.
|
||||
|
||||
package resource
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
expectedHostID = "f2c668b579780554f70f72a063dc0864"
|
||||
|
||||
readFileNoError = func(filename string) (string, error) {
|
||||
return expectedHostID + "\n", nil
|
||||
}
|
||||
|
||||
readFileError = func(filename string) (string, error) {
|
||||
return "", errors.New("not found")
|
||||
}
|
||||
|
||||
execCommandNoError = func(string, ...string) (string, error) {
|
||||
return expectedHostID + "\n", nil
|
||||
}
|
||||
|
||||
execCommandError = func(string, ...string) (string, error) {
|
||||
return "", errors.New("not found")
|
||||
}
|
||||
)
|
||||
|
||||
func SetDefaultHostIDProvider() {
|
||||
SetHostIDProvider(defaultHostIDProvider)
|
||||
}
|
||||
|
||||
func SetHostIDProvider(hostIDProvider hostIDProvider) {
|
||||
hostID = hostIDProvider
|
||||
}
|
||||
|
||||
func TestHostIDReaderBSD(t *testing.T) {
|
||||
tt := []struct {
|
||||
name string
|
||||
fileReader fileReader
|
||||
commandExecutor commandExecutor
|
||||
expectedHostID string
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "hostIDReaderBSD valid primary",
|
||||
fileReader: readFileNoError,
|
||||
commandExecutor: execCommandError,
|
||||
expectedHostID: expectedHostID,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "hostIDReaderBSD invalid primary",
|
||||
fileReader: readFileError,
|
||||
commandExecutor: execCommandNoError,
|
||||
expectedHostID: expectedHostID,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "hostIDReaderBSD invalid primary and secondary",
|
||||
fileReader: readFileError,
|
||||
commandExecutor: execCommandError,
|
||||
expectedHostID: "",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
tc := tc
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
reader := hostIDReaderBSD{
|
||||
readFile: tc.fileReader,
|
||||
execCommand: tc.commandExecutor,
|
||||
}
|
||||
hostID, err := reader.read()
|
||||
require.Equal(t, tc.expectError, err != nil)
|
||||
require.Equal(t, tc.expectedHostID, hostID)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostIDReaderLinux(t *testing.T) {
|
||||
readFilePrimaryError := func(filename string) (string, error) {
|
||||
if filename == "/var/lib/dbus/machine-id" {
|
||||
return readFileNoError(filename)
|
||||
}
|
||||
return readFileError(filename)
|
||||
}
|
||||
|
||||
tt := []struct {
|
||||
name string
|
||||
fileReader fileReader
|
||||
expectedHostID string
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "hostIDReaderLinux valid primary",
|
||||
fileReader: readFileNoError,
|
||||
expectedHostID: expectedHostID,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "hostIDReaderLinux invalid primary",
|
||||
fileReader: readFilePrimaryError,
|
||||
expectedHostID: expectedHostID,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "hostIDReaderLinux invalid primary and secondary",
|
||||
fileReader: readFileError,
|
||||
expectedHostID: "",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
tc := tc
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
reader := hostIDReaderLinux{
|
||||
readFile: tc.fileReader,
|
||||
}
|
||||
hostID, err := reader.read()
|
||||
require.Equal(t, tc.expectError, err != nil)
|
||||
require.Equal(t, tc.expectedHostID, hostID)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostIDReaderDarwin(t *testing.T) {
|
||||
validOutput := `+-o J316sAP <class IOPlatformExpertDevice, id 0x10000024d, registered, matched, active, busy 0 (132196 ms), retain 37>
|
||||
{
|
||||
"IOPolledInterface" = "AppleARMWatchdogTimerHibernateHandler is not serializable"
|
||||
"#address-cells" = <02000000>
|
||||
"AAPL,phandle" = <01000000>
|
||||
"serial-number" = <94e1c79ec04cd3f153f600000000000000000000000000000000000000000000>
|
||||
"IOBusyInterest" = "IOCommand is not serializable"
|
||||
"target-type" = <"J316s">
|
||||
"platform-name" = <7436303030000000000000000000000000000000000000000000000000000000>
|
||||
"secure-root-prefix" = <"md">
|
||||
"name" = <"device-tree">
|
||||
"region-info" = <4c4c2f4100000000000000000000000000000000000000000000000000000000>
|
||||
"manufacturer" = <"Apple Inc.">
|
||||
"compatible" = <"J316sAP","MacBookPro18,1","AppleARM">
|
||||
"config-number" = <00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000>
|
||||
"IOPlatformSerialNumber" = "HDWLIF2LM7"
|
||||
"regulatory-model-number" = <4132343835000000000000000000000000000000000000000000000000000000>
|
||||
"time-stamp" = <"Fri Aug 5 20:25:38 PDT 2022">
|
||||
"clock-frequency" = <00366e01>
|
||||
"model" = <"MacBookPro18,1">
|
||||
"mlb-serial-number" = <5c92d268d6cd789e475ffafc0d363fc950000000000000000000000000000000>
|
||||
"model-number" = <5a31345930303136430000000000000000000000000000000000000000000000>
|
||||
"IONWInterrupts" = "IONWInterrupts"
|
||||
"model-config" = <"ICT;MoPED=0x03D053A605C84ED11C455A18D6C643140B41A239">
|
||||
"device_type" = <"bootrom">
|
||||
"#size-cells" = <02000000>
|
||||
"IOPlatformUUID" = "81895B8D-9EF9-4EBB-B5DE-B00069CF53F0"
|
||||
}
|
||||
`
|
||||
execCommandValid := func(string, ...string) (string, error) {
|
||||
return validOutput, nil
|
||||
}
|
||||
|
||||
execCommandInvalid := func(string, ...string) (string, error) {
|
||||
return "wasn't expecting this", nil
|
||||
}
|
||||
|
||||
tt := []struct {
|
||||
name string
|
||||
fileReader fileReader
|
||||
commandExecutor commandExecutor
|
||||
expectedHostID string
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "hostIDReaderDarwin valid output",
|
||||
commandExecutor: execCommandValid,
|
||||
expectedHostID: "81895B8D-9EF9-4EBB-B5DE-B00069CF53F0",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "hostIDReaderDarwin invalid output",
|
||||
commandExecutor: execCommandInvalid,
|
||||
expectedHostID: "",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "hostIDReaderDarwin error",
|
||||
commandExecutor: execCommandError,
|
||||
expectedHostID: "",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
reader := hostIDReaderDarwin{
|
||||
execCommand: tc.commandExecutor,
|
||||
}
|
||||
hostID, err := reader.read()
|
||||
require.Equal(t, tc.expectError, err != nil)
|
||||
require.Equal(t, tc.expectedHostID, hostID)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
// 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.
|
||||
|
||||
// +build !darwin
|
||||
// +build !dragonfly
|
||||
// +build !freebsd
|
||||
// +build !linux
|
||||
// +build !netbsd
|
||||
// +build !openbsd
|
||||
// +build !solaris
|
||||
// +build !windows
|
||||
|
||||
package resource // import "go.opentelemetry.io/otel/sdk/resource"
|
||||
|
||||
// hostIDReaderUnsupported is a placeholder implementation for operating systems
|
||||
// for which this project currently doesn't support host.id
|
||||
// attribute detection. See build tags declaration early on this file
|
||||
// for a list of unsupported OSes.
|
||||
type hostIDReaderUnsupported struct{}
|
||||
|
||||
func (*hostIDReaderUnsupported) read() (string, error) {
|
||||
return "<unknown>", nil
|
||||
}
|
||||
|
||||
var platformHostIDReader hostIDReader = &hostIDReaderUnsupported{}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
// 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 windows
|
||||
// +build windows
|
||||
|
||||
package resource // import "go.opentelemetry.io/otel/sdk/resource"
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
// implements hostIDReader
|
||||
type hostIDReaderWindows struct{}
|
||||
|
||||
// read reads MachineGuid from the windows registry key:
|
||||
// SOFTWARE\Microsoft\Cryptography
|
||||
func (*hostIDReaderWindows) read() (string, error) {
|
||||
k, err := registry.OpenKey(
|
||||
registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Cryptography`,
|
||||
registry.QUERY_VALUE|registry.WOW64_64KEY,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer k.Close()
|
||||
|
||||
guid, _, err := k.GetStringValue("MachineGuid")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return guid, nil
|
||||
}
|
||||
|
||||
var platformHostIDReader hostIDReader = &hostIDReaderWindows{}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// 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 windows
|
||||
// +build windows
|
||||
|
||||
package resource // import "go.opentelemetry.io/otel/sdk/resource"
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestReader(t *testing.T) {
|
||||
reader := &hostIDReaderWindows{}
|
||||
result, err := reader.read()
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, result)
|
||||
}
|
||||
|
|
@ -471,6 +471,36 @@ func TestNewWrapedError(t *testing.T) {
|
|||
assert.NotErrorIs(t, err, errors.New("false positive error"))
|
||||
}
|
||||
|
||||
func TestWithHostID(t *testing.T) {
|
||||
mockHostIDProvider()
|
||||
t.Cleanup(restoreHostIDProvider)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
res, err := resource.New(ctx,
|
||||
resource.WithHostID(),
|
||||
)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, map[string]string{
|
||||
"host.id": "f2c668b579780554f70f72a063dc0864",
|
||||
}, toMap(res))
|
||||
}
|
||||
|
||||
func TestWithHostIDError(t *testing.T) {
|
||||
mockHostIDProviderWithError()
|
||||
t.Cleanup(restoreHostIDProvider)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
res, err := resource.New(ctx,
|
||||
resource.WithHostID(),
|
||||
)
|
||||
|
||||
assert.ErrorIs(t, err, assert.AnError)
|
||||
require.EqualValues(t, map[string]string{}, toMap(res))
|
||||
}
|
||||
|
||||
func TestWithOSType(t *testing.T) {
|
||||
mockRuntimeProviders()
|
||||
t.Cleanup(restoreAttributesProviders)
|
||||
|
|
|
|||
Loading…
Reference in New Issue