From 21c8ab836a4cb2f80dccf064b2d2597ad795a78a Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Tue, 16 Apr 2024 17:21:30 +0200 Subject: [PATCH 01/19] Add host resource detector --- .github/dependabot.yml | 9 ++ CHANGELOG.md | 1 + detectors/host/go.mod | 20 +++++ detectors/host/go.sum | 27 ++++++ detectors/host/host.go | 137 ++++++++++++++++++++++++++++++ detectors/host/host_id_darwin.go | 21 +++++ detectors/host/host_id_linux.go | 21 +++++ detectors/host/host_id_windows.go | 24 ++++++ detectors/host/host_test.go | 73 ++++++++++++++++ 9 files changed, 333 insertions(+) create mode 100644 detectors/host/go.mod create mode 100644 detectors/host/go.sum create mode 100644 detectors/host/host.go create mode 100644 detectors/host/host_id_darwin.go create mode 100644 detectors/host/host_id_linux.go create mode 100644 detectors/host/host_id_windows.go create mode 100644 detectors/host/host_test.go diff --git a/.github/dependabot.yml b/.github/dependabot.yml index bb6bf7d7278..3866424ba7e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -172,6 +172,15 @@ updates: schedule: interval: weekly day: sunday + - package-ecosystem: gomod + directory: /detectors/host + labels: + - dependencies + - go + - Skip Changelog + schedule: + interval: weekly + day: sunday - package-ecosystem: gomod directory: /exporters/autoexport labels: diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ef0d841922..a78e7a16dc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Add the new `go.opentelemetry.io/contrib/instrgen` package to provide auto-generated source code instrumentation. (#3068, #3108) - `NewSDK` in `go.opentelemetry.io/contrib/config` now returns a configured SDK with a valid `MeterProvider`. (#4804) +- Add resource detector for host data. ### Fixed diff --git a/detectors/host/go.mod b/detectors/host/go.mod new file mode 100644 index 00000000000..aca83de3dd8 --- /dev/null +++ b/detectors/host/go.mod @@ -0,0 +1,20 @@ +module go.opentelemetry.io/contrib/detectors/host + +go 1.21 + +require ( + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/otel v1.25.0 + go.opentelemetry.io/otel/sdk v1.25.0 + golang.org/x/sys v0.18.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + go.opentelemetry.io/otel/metric v1.25.0 // indirect + go.opentelemetry.io/otel/trace v1.25.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/detectors/host/go.sum b/detectors/host/go.sum new file mode 100644 index 00000000000..c94c7b1876b --- /dev/null +++ b/detectors/host/go.sum @@ -0,0 +1,27 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +go.opentelemetry.io/otel v1.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k= +go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg= +go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA= +go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s= +go.opentelemetry.io/otel/sdk v1.25.0 h1:PDryEJPC8YJZQSyLY5eqLeafHtG+X7FWnf3aXMtxbqo= +go.opentelemetry.io/otel/sdk v1.25.0/go.mod h1:oFgzCM2zdsxKzz6zwpTZYLLQsFwc+K0daArPdIhuxkw= +go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM= +go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/detectors/host/host.go b/detectors/host/host.go new file mode 100644 index 00000000000..9430662da86 --- /dev/null +++ b/detectors/host/host.go @@ -0,0 +1,137 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package host // import "go.opentelemetry.io/contrib/detectors/host" + +import ( + "context" + "net" + "os" + "runtime" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/resource" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" +) + +type config struct { + optInIPAddresses bool + optInMACAddresses bool +} + +func newConfig(options ...Option) *config { + c := &config{} + for _, option := range options { + option.apply(c) + } + + return c +} + +// Option applies an Azure VM detector configuration option. +type Option interface { + apply(*config) +} + +type optionFunc func(*config) + +func (fn optionFunc) apply(c *config) { + fn(c) +} + +// WithIPAddresses adds the optional attribute `host.ip`. +func WithIPAddresses() Option { + return optionFunc(func(c *config) { + c.optInIPAddresses = true + }) +} + +// WithMACAddresses adds the optional attribute `host.ip`. +func WithMACAddresses() Option { + return optionFunc(func(c *config) { + c.optInMACAddresses = true + }) +} + +type resourceDetector struct { + config *config +} + +// NewResourceDetector returns a resource detector that will detect host resources. +func NewResourceDetector(opts ...Option) resource.Detector { + c := newConfig(opts...) + return &resourceDetector{config: c} +} + +// Detect detects associated resources when running on a physical host. +func (detector *resourceDetector) Detect(ctx context.Context) (*resource.Resource, error) { + attributes := []attribute.KeyValue{ + semconv.HostArchKey.String(runtime.GOARCH), + } + + hostName, err := os.Hostname() + if err == nil { + attributes = append(attributes, semconv.HostName(hostName)) + } + + machineId, err := getHostId() + if err == nil { + attributes = append(attributes, semconv.HostID(machineId)) + } + + if detector.config.optInIPAddresses { + ipAddresses := getIPAddresses() + if len(ipAddresses) > 0 { + attributes = append(attributes, semconv.HostIP(ipAddresses...)) + } + } + + if detector.config.optInMACAddresses { + macAddresses := getMACAddresses() + if len(macAddresses) > 0 { + attributes = append(attributes, semconv.HostMac(macAddresses...)) + } + } + + return resource.NewWithAttributes(semconv.SchemaURL, attributes...), nil +} + +func getIPAddresses() []string { + var ipAddresses []string + + ifaces, err := net.Interfaces() + if err == nil { + for _, iface := range ifaces { + if iface.Flags&net.FlagLoopback != 0 { + continue + } + + addrs, err := iface.Addrs() + if err != nil { + continue + } + for _, addr := range addrs { + ipAddresses = append(ipAddresses, addr.String()) + } + } + } + + return ipAddresses +} + +func getMACAddresses() []string { + var macAddresses []string + + ifaces, err := net.Interfaces() + if err == nil { + for _, iface := range ifaces { + if iface.Flags&net.FlagLoopback != 0 { + continue + } + + macAddresses = append(macAddresses, iface.HardwareAddr.String()) + } + } + + return macAddresses +} diff --git a/detectors/host/host_id_darwin.go b/detectors/host/host_id_darwin.go new file mode 100644 index 00000000000..840fe552740 --- /dev/null +++ b/detectors/host/host_id_darwin.go @@ -0,0 +1,21 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +//go:build darwin +// +build darwin + +package host // import "go.opentelemetry.io/contrib/detectors/host" + +import ( + "os/exec" + "strings" +) + +func getHostId() (string, error) { + machineId, err := exec.Command("ioreg", "-rd1", "-c", "IOPlatformExpertDevice").Output() + if err != nil { + return "", err + } + + return strings.Trim(string(machineId), "\n"), nil +} diff --git a/detectors/host/host_id_linux.go b/detectors/host/host_id_linux.go new file mode 100644 index 00000000000..0688df7fdc7 --- /dev/null +++ b/detectors/host/host_id_linux.go @@ -0,0 +1,21 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +//go:build linux +// +build linux + +package host // import "go.opentelemetry.io/contrib/detectors/host" + +import ( + "os" + "strings" +) + +func getHostId() (string, error) { + machineId, err := os.ReadFile("/etc/machine-id") + if err != nil { + return "", err + } + + return strings.Trim(string(machineId), "\n"), nil +} diff --git a/detectors/host/host_id_windows.go b/detectors/host/host_id_windows.go new file mode 100644 index 00000000000..e0a26b45911 --- /dev/null +++ b/detectors/host/host_id_windows.go @@ -0,0 +1,24 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +//go:build windows +// +build windows + +package host // import "go.opentelemetry.io/contrib/detectors/host" + +import ( + "golang.org/x/sys/windows/registry" +) + +func getHostId() (string, error) { + key, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Cryptography`, registry.QUERY_VALUE) + if err != nil { + return "", err + } + + defer key.Close() + + machineId, _, err := key.GetStringValue("MachineGuid") + + return machineId, err +} diff --git a/detectors/host/host_test.go b/detectors/host/host_test.go new file mode 100644 index 00000000000..c47687332f4 --- /dev/null +++ b/detectors/host/host_test.go @@ -0,0 +1,73 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package host + +import ( + "context" + "os" + "runtime" + "testing" + + "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/resource" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" +) + +func Test_DetectLinux(t *testing.T) { + detector := NewResourceDetector() + + hostResource, err := detector.Detect(context.Background()) + + assert.True(t, err == nil) + + hostName, _ := os.Hostname() + + attributes := []attribute.KeyValue{ + semconv.HostArchKey.String(runtime.GOARCH), + semconv.HostName(hostName), + } + + // The host id is added conditionally, as it might not be available under all circumstances (for example in Windows containers) + machineId, err := getHostId() + if err == nil { + attributes = append(attributes, semconv.HostID(machineId)) + } + + expectedResource := resource.NewWithAttributes(semconv.SchemaURL, attributes...) + + assert.Equal(t, expectedResource, hostResource) +} + +func Test_DetectLinux_WithOptIns(t *testing.T) { + detector := NewResourceDetector( + WithIPAddresses(), + WithMACAddresses(), + ) + + hostResource, err := detector.Detect(context.Background()) + + assert.True(t, err == nil) + + hostName, _ := os.Hostname() + + attributes := []attribute.KeyValue{ + semconv.HostArchKey.String(runtime.GOARCH), + semconv.HostName(hostName), + } + + // The host id is added conditionally, as it might not be available under all circumstances (for example in Windows containers) + machineId, err := getHostId() + if err == nil { + attributes = append(attributes, semconv.HostID(machineId)) + } + + attributes = append(attributes, semconv.HostIP(getIPAddresses()...)) + attributes = append(attributes, semconv.HostMac(getMACAddresses()...)) + + expectedResource := resource.NewWithAttributes(semconv.SchemaURL, attributes...) + + assert.Equal(t, expectedResource, hostResource) +} From 605afe8d67abe4f4bbe428a2332080f9a6c7bc4e Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Tue, 16 Apr 2024 17:25:11 +0200 Subject: [PATCH 02/19] Remove obsolete postfix --- detectors/host/host_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detectors/host/host_test.go b/detectors/host/host_test.go index c47687332f4..0df8020865e 100644 --- a/detectors/host/host_test.go +++ b/detectors/host/host_test.go @@ -16,7 +16,7 @@ import ( semconv "go.opentelemetry.io/otel/semconv/v1.24.0" ) -func Test_DetectLinux(t *testing.T) { +func Test_Detect(t *testing.T) { detector := NewResourceDetector() hostResource, err := detector.Detect(context.Background()) @@ -41,7 +41,7 @@ func Test_DetectLinux(t *testing.T) { assert.Equal(t, expectedResource, hostResource) } -func Test_DetectLinux_WithOptIns(t *testing.T) { +func Test_Detect_WithOptIns(t *testing.T) { detector := NewResourceDetector( WithIPAddresses(), WithMACAddresses(), From 4c5d456e4fd672b0fa69db91df1e028c4155fadd Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Tue, 16 Apr 2024 17:39:03 +0200 Subject: [PATCH 03/19] Add README --- detectors/host/README.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 detectors/host/README.md diff --git a/detectors/host/README.md b/detectors/host/README.md new file mode 100644 index 00000000000..0693abb09c5 --- /dev/null +++ b/detectors/host/README.md @@ -0,0 +1,35 @@ +# Host Resource detector + +The host resource detector supports detecting host-specific attributes on physical hosts. + +## Usage + +```golang +// Instantiate a new host resource detector +hostResourceDetector := host.NewResourceDetector() +resource, err := hostResourceDetector.Detect(context.Background()) +``` + +To populate optional attributes, the resource detector constructor accepts functional options `WithIPAddresses` to enable `host.ip`, and `WithMACAddresses` to enable `host.mac`. + +```golang +// Instantiate a new host resource detector with all opt-in attributes +hostResourceDetector := host.NewResourceDetector( + WithIPAddresses(), + WithMACAddresses(), +) +resource, err := hostResourceDetector.Detect(context.Background()) +``` + +## Supported attributes + +According to [semantic conventions for host resources](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/host.md), each of the following attributes is added if it is available: + +* `host.arch` +* `host.id` +* `host.name` + +The following attributes require an explicit opt-in during the initialization of the host resource detector: + +* `host.ip` +* `host.mac` From 055f721a0283a8dd2531f015e9a4d8296e43caa5 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Tue, 16 Apr 2024 18:07:04 +0200 Subject: [PATCH 04/19] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a78e7a16dc9..69a3f4edc66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Add the new `go.opentelemetry.io/contrib/instrgen` package to provide auto-generated source code instrumentation. (#3068, #3108) - `NewSDK` in `go.opentelemetry.io/contrib/config` now returns a configured SDK with a valid `MeterProvider`. (#4804) -- Add resource detector for host data. +- Add the new `go.opentelemetry.io/contrib/detectors/host` package to provide a resource detector for physical hosts. (#5399) ### Fixed From c32b3edc236ee077fbf28b44eea0c5e79747c20f Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 13:35:15 +0200 Subject: [PATCH 05/19] Update detectors/host/host.go Co-authored-by: Tyler Yahn --- detectors/host/host.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/host/host.go b/detectors/host/host.go index 9430662da86..c0f55652931 100644 --- a/detectors/host/host.go +++ b/detectors/host/host.go @@ -28,7 +28,7 @@ func newConfig(options ...Option) *config { return c } -// Option applies an Azure VM detector configuration option. +// Option applies a host detector configuration option. type Option interface { apply(*config) } From 3cfd6e898f125e6ee141b7785f3f720614ea765e Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 13:35:21 +0200 Subject: [PATCH 06/19] Update detectors/host/host.go Co-authored-by: Tyler Yahn --- detectors/host/host.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/host/host.go b/detectors/host/host.go index c0f55652931..aaf6ec128b2 100644 --- a/detectors/host/host.go +++ b/detectors/host/host.go @@ -46,7 +46,7 @@ func WithIPAddresses() Option { }) } -// WithMACAddresses adds the optional attribute `host.ip`. +// WithMACAddresses adds the optional attribute "host.mac". func WithMACAddresses() Option { return optionFunc(func(c *config) { c.optInMACAddresses = true From b00dc6d0c9b8a44eef40ee170922957f54c89426 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 13:35:26 +0200 Subject: [PATCH 07/19] Update detectors/host/host.go Co-authored-by: Tyler Yahn --- detectors/host/host.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/host/host.go b/detectors/host/host.go index aaf6ec128b2..332c6bf2747 100644 --- a/detectors/host/host.go +++ b/detectors/host/host.go @@ -39,7 +39,7 @@ func (fn optionFunc) apply(c *config) { fn(c) } -// WithIPAddresses adds the optional attribute `host.ip`. +// WithIPAddresses adds the optional attribute "host.ip". func WithIPAddresses() Option { return optionFunc(func(c *config) { c.optInIPAddresses = true From 2ca2dca267f7099659e6e9505afbd5a1dd1c0490 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 13:35:34 +0200 Subject: [PATCH 08/19] Update detectors/host/host.go Co-authored-by: Tyler Yahn --- detectors/host/host.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/host/host.go b/detectors/host/host.go index 332c6bf2747..1bf83688f50 100644 --- a/detectors/host/host.go +++ b/detectors/host/host.go @@ -57,7 +57,7 @@ type resourceDetector struct { config *config } -// NewResourceDetector returns a resource detector that will detect host resources. +// NewResourceDetector returns a [resource.Detector] that will detect host resources. func NewResourceDetector(opts ...Option) resource.Detector { c := newConfig(opts...) return &resourceDetector{config: c} From 0c16b7025c6b79463123d6fd432687c77dc02fb5 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 13:35:55 +0200 Subject: [PATCH 09/19] Update detectors/host/host.go Co-authored-by: Tyler Yahn --- detectors/host/host.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/host/host.go b/detectors/host/host.go index 1bf83688f50..8be8f41b8ca 100644 --- a/detectors/host/host.go +++ b/detectors/host/host.go @@ -58,7 +58,7 @@ type resourceDetector struct { } // NewResourceDetector returns a [resource.Detector] that will detect host resources. -func NewResourceDetector(opts ...Option) resource.Detector { +func New(opts ...Option) resource.Detector { c := newConfig(opts...) return &resourceDetector{config: c} } From 2a98f05fc4e61edbac23ddd8358e6586c8e101fc Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 13:36:02 +0200 Subject: [PATCH 10/19] Update detectors/host/host_test.go Co-authored-by: Tyler Yahn --- detectors/host/host_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/host/host_test.go b/detectors/host/host_test.go index 0df8020865e..97ee9054c4d 100644 --- a/detectors/host/host_test.go +++ b/detectors/host/host_test.go @@ -16,7 +16,7 @@ import ( semconv "go.opentelemetry.io/otel/semconv/v1.24.0" ) -func Test_Detect(t *testing.T) { +func TestDetect(t *testing.T) { detector := NewResourceDetector() hostResource, err := detector.Detect(context.Background()) From d976eeb847c98675f90445207603e2fca784e6df Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 13:36:15 +0200 Subject: [PATCH 11/19] Update detectors/host/host_test.go Co-authored-by: Tyler Yahn --- detectors/host/host_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/detectors/host/host_test.go b/detectors/host/host_test.go index 97ee9054c4d..66f2a68f782 100644 --- a/detectors/host/host_test.go +++ b/detectors/host/host_test.go @@ -20,8 +20,7 @@ func TestDetect(t *testing.T) { detector := NewResourceDetector() hostResource, err := detector.Detect(context.Background()) - - assert.True(t, err == nil) + assert.NoError(t, err) hostName, _ := os.Hostname() From 2a14b6f3ae130075992e04b8d0763ae2b89822b3 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 13:36:24 +0200 Subject: [PATCH 12/19] Update detectors/host/host_test.go Co-authored-by: Tyler Yahn --- detectors/host/host_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/host/host_test.go b/detectors/host/host_test.go index 66f2a68f782..59760aad405 100644 --- a/detectors/host/host_test.go +++ b/detectors/host/host_test.go @@ -40,7 +40,7 @@ func TestDetect(t *testing.T) { assert.Equal(t, expectedResource, hostResource) } -func Test_Detect_WithOptIns(t *testing.T) { +func TestDetectWithOptIns(t *testing.T) { detector := NewResourceDetector( WithIPAddresses(), WithMACAddresses(), From 20a8a67a07f2d07cda9b8a034d059356f2df41f6 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 13:36:51 +0200 Subject: [PATCH 13/19] Update detectors/host/host_id_windows.go Co-authored-by: Tyler Yahn --- detectors/host/host_id_windows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/host/host_id_windows.go b/detectors/host/host_id_windows.go index e0a26b45911..10bd0ff6685 100644 --- a/detectors/host/host_id_windows.go +++ b/detectors/host/host_id_windows.go @@ -11,7 +11,7 @@ import ( ) func getHostId() (string, error) { - key, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Cryptography`, registry.QUERY_VALUE) + key, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Cryptography`, registry.QUERY_VALUE|registry.WOW64_64KEY) if err != nil { return "", err } From 8b7b4d5d1485f0483b41a52d20c8cb43d98d1041 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 13:37:07 +0200 Subject: [PATCH 14/19] Update detectors/host/README.md Co-authored-by: Tyler Yahn --- detectors/host/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/host/README.md b/detectors/host/README.md index 0693abb09c5..da36706b6e7 100644 --- a/detectors/host/README.md +++ b/detectors/host/README.md @@ -23,7 +23,7 @@ resource, err := hostResourceDetector.Detect(context.Background()) ## Supported attributes -According to [semantic conventions for host resources](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/host.md), each of the following attributes is added if it is available: +According to [semantic conventions for host resources](https://opentelemetry.io/docs/specs/semconv/resource/host/), each of the following attributes is added if it is available: * `host.arch` * `host.id` From 15ae5a8130bdf84e270eb570772aef84786d5f82 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 13:37:23 +0200 Subject: [PATCH 15/19] Update detectors/host/host.go Co-authored-by: Tyler Yahn --- detectors/host/host.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/host/host.go b/detectors/host/host.go index 8be8f41b8ca..98f1aede180 100644 --- a/detectors/host/host.go +++ b/detectors/host/host.go @@ -30,7 +30,7 @@ func newConfig(options ...Option) *config { // Option applies a host detector configuration option. type Option interface { - apply(*config) + apply(config) config } type optionFunc func(*config) From c1ac4e7c1bf7c703efc74ac05c1925161559b457 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 13:37:40 +0200 Subject: [PATCH 16/19] Add host detector to experimental packages --- versions.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/versions.yaml b/versions.yaml index 0513ed39d41..69b73d89975 100644 --- a/versions.yaml +++ b/versions.yaml @@ -20,6 +20,7 @@ module-sets: modules: - go.opentelemetry.io/contrib/bridges/prometheus - go.opentelemetry.io/contrib/detectors/aws/lambda + - go.opentelemetry.io/contrib/detectors/host - go.opentelemetry.io/contrib/exporters/autoexport - go.opentelemetry.io/contrib/propagators/autoprop - go.opentelemetry.io/contrib/propagators/opencensus From 1fe638574a4c36dd913aaf42102f2f5c4f8c52fd Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 13:53:00 +0200 Subject: [PATCH 17/19] PR comments --- detectors/host/host_id_bsd.go | 27 ++++++++++++++++++++++ detectors/host/host_id_unsupported.go | 32 +++++++++++++++++++++++++++ detectors/host/host_test.go | 18 +++++++++++---- 3 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 detectors/host/host_id_bsd.go create mode 100644 detectors/host/host_id_unsupported.go diff --git a/detectors/host/host_id_bsd.go b/detectors/host/host_id_bsd.go new file mode 100644 index 00000000000..44019190191 --- /dev/null +++ b/detectors/host/host_id_bsd.go @@ -0,0 +1,27 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +//go:build dragonfly || freebsd || netbsd || openbsd || solaris +// +build dragonfly freebsd netbsd openbsd solaris + +package host // import "go.opentelemetry.io/contrib/detectors/host" + +import ( + "os" + "os/exec" + "strings" +) + +func getHostId() (string, error) { + machineId, err := os.ReadFile("/etc/machine-id") + if err == nil { + return strings.Trim(string(machineId), "\n"), nil + } + + machineId, err = exec.Command("kenv", "-q", "smbios.system.uuid") + if err == nil { + return strings.Trim(string(machineId), "\n"), nil + } + + return "", errors.New("host id not found in: /etc/hostid or kenv") +} diff --git a/detectors/host/host_id_unsupported.go b/detectors/host/host_id_unsupported.go new file mode 100644 index 00000000000..52edc1ad57d --- /dev/null +++ b/detectors/host/host_id_unsupported.go @@ -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. + +// +build !darwin +// +build !dragonfly +// +build !freebsd +// +build !linux +// +build !netbsd +// +build !openbsd +// +build !solaris +// +build !windows + +package host // import "go.opentelemetry.io/contrib/detectors/host" + +// 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. +func getHostId() (string, error) { + return "", nil +} diff --git a/detectors/host/host_test.go b/detectors/host/host_test.go index 59760aad405..8a5ff2d505b 100644 --- a/detectors/host/host_test.go +++ b/detectors/host/host_test.go @@ -22,11 +22,15 @@ func TestDetect(t *testing.T) { hostResource, err := detector.Detect(context.Background()) assert.NoError(t, err) - hostName, _ := os.Hostname() - attributes := []attribute.KeyValue{ semconv.HostArchKey.String(runtime.GOARCH), - semconv.HostName(hostName), + } + + hostName, err := os.Hostname() + + // The host name is added conditionally, as it might not be available under all circumstances + if err == nil { + attributes = append(attributes, semconv.HostName(hostName)) } // The host id is added conditionally, as it might not be available under all circumstances (for example in Windows containers) @@ -54,7 +58,13 @@ func TestDetectWithOptIns(t *testing.T) { attributes := []attribute.KeyValue{ semconv.HostArchKey.String(runtime.GOARCH), - semconv.HostName(hostName), + } + + hostName, err := os.Hostname() + + // The host name is added conditionally, as it might not be available under all circumstances + if err == nil { + attributes = append(attributes, semconv.HostName(hostName)) } // The host id is added conditionally, as it might not be available under all circumstances (for example in Windows containers) From ffa6502ef5a9346d2ba1ea2a95f4872df2ee9636 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 14:00:32 +0200 Subject: [PATCH 18/19] PR comments --- detectors/host/host.go | 22 +++++++++++++--------- detectors/host/host_id_bsd.go | 3 ++- detectors/host/host_id_unsupported.go | 13 +------------ detectors/host/host_test.go | 6 ++---- 4 files changed, 18 insertions(+), 26 deletions(-) diff --git a/detectors/host/host.go b/detectors/host/host.go index 98f1aede180..30327ca4f99 100644 --- a/detectors/host/host.go +++ b/detectors/host/host.go @@ -19,10 +19,10 @@ type config struct { optInMACAddresses bool } -func newConfig(options ...Option) *config { - c := &config{} +func newConfig(options ...Option) config { + c := config{} for _, option := range options { - option.apply(c) + c = option.apply(c) } return c @@ -33,28 +33,32 @@ type Option interface { apply(config) config } -type optionFunc func(*config) +type optionFunc func(config) config -func (fn optionFunc) apply(c *config) { - fn(c) +func (fn optionFunc) apply(c config) config { + return fn(c) } // WithIPAddresses adds the optional attribute "host.ip". func WithIPAddresses() Option { - return optionFunc(func(c *config) { + return optionFunc(func(c config) config { c.optInIPAddresses = true + + return c }) } // WithMACAddresses adds the optional attribute "host.mac". func WithMACAddresses() Option { - return optionFunc(func(c *config) { + return optionFunc(func(c config) config { c.optInMACAddresses = true + + return c }) } type resourceDetector struct { - config *config + config config } // NewResourceDetector returns a [resource.Detector] that will detect host resources. diff --git a/detectors/host/host_id_bsd.go b/detectors/host/host_id_bsd.go index 44019190191..f0d48514cbe 100644 --- a/detectors/host/host_id_bsd.go +++ b/detectors/host/host_id_bsd.go @@ -7,6 +7,7 @@ package host // import "go.opentelemetry.io/contrib/detectors/host" import ( + "errors" "os" "os/exec" "strings" @@ -18,7 +19,7 @@ func getHostId() (string, error) { return strings.Trim(string(machineId), "\n"), nil } - machineId, err = exec.Command("kenv", "-q", "smbios.system.uuid") + machineId, err = exec.Command("kenv", "-q", "smbios.system.uuid").Output() if err == nil { return strings.Trim(string(machineId), "\n"), nil } diff --git a/detectors/host/host_id_unsupported.go b/detectors/host/host_id_unsupported.go index 52edc1ad57d..e0c554f00b7 100644 --- a/detectors/host/host_id_unsupported.go +++ b/detectors/host/host_id_unsupported.go @@ -1,16 +1,5 @@ // 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. +// SPDX-License-Identifier: Apache-2.0 // +build !darwin // +build !dragonfly diff --git a/detectors/host/host_test.go b/detectors/host/host_test.go index 8a5ff2d505b..8a5397aa57d 100644 --- a/detectors/host/host_test.go +++ b/detectors/host/host_test.go @@ -17,7 +17,7 @@ import ( ) func TestDetect(t *testing.T) { - detector := NewResourceDetector() + detector := New() hostResource, err := detector.Detect(context.Background()) assert.NoError(t, err) @@ -45,7 +45,7 @@ func TestDetect(t *testing.T) { } func TestDetectWithOptIns(t *testing.T) { - detector := NewResourceDetector( + detector := New( WithIPAddresses(), WithMACAddresses(), ) @@ -54,8 +54,6 @@ func TestDetectWithOptIns(t *testing.T) { assert.True(t, err == nil) - hostName, _ := os.Hostname() - attributes := []attribute.KeyValue{ semconv.HostArchKey.String(runtime.GOARCH), } From f58599095d7133d4d0252400eae92d5ac9351b6c Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 14:30:23 +0200 Subject: [PATCH 19/19] PR comments --- detectors/host/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detectors/host/README.md b/detectors/host/README.md index da36706b6e7..ca6c9367385 100644 --- a/detectors/host/README.md +++ b/detectors/host/README.md @@ -6,7 +6,7 @@ The host resource detector supports detecting host-specific attributes on physic ```golang // Instantiate a new host resource detector -hostResourceDetector := host.NewResourceDetector() +hostResourceDetector := host.New() resource, err := hostResourceDetector.Detect(context.Background()) ``` @@ -14,7 +14,7 @@ To populate optional attributes, the resource detector constructor accepts funct ```golang // Instantiate a new host resource detector with all opt-in attributes -hostResourceDetector := host.NewResourceDetector( +hostResourceDetector := host.New( WithIPAddresses(), WithMACAddresses(), )