From 60681882920a1b6d2e644fddd82a9bea9203f637 Mon Sep 17 00:00:00 2001 From: Dakota Paasman <122491662+dpaasman00@users.noreply.github.com> Date: Wed, 16 Oct 2024 15:28:38 -0400 Subject: [PATCH] refactor to gopsutil --- extension/opampextension/go.mod | 2 +- .../internal/util/package_test.go | 14 -- .../opampextension/internal/util/parse.go | 51 ------- .../internal/util/parse_test.go | 128 ------------------ extension/opampextension/opamp_agent.go | 39 ++---- extension/opampextension/opamp_agent_test.go | 99 ++++++-------- 6 files changed, 56 insertions(+), 277 deletions(-) delete mode 100644 extension/opampextension/internal/util/package_test.go delete mode 100644 extension/opampextension/internal/util/parse.go delete mode 100644 extension/opampextension/internal/util/parse_test.go diff --git a/extension/opampextension/go.mod b/extension/opampextension/go.mod index 99ee8a4a67d3..c6a8b3d73232 100644 --- a/extension/opampextension/go.mod +++ b/extension/opampextension/go.mod @@ -57,7 +57,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.28.0 // indirect golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.17.0 // indirect + golang.org/x/text v0.17.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect google.golang.org/grpc v1.67.1 // indirect google.golang.org/protobuf v1.35.1 // indirect diff --git a/extension/opampextension/internal/util/package_test.go b/extension/opampextension/internal/util/package_test.go deleted file mode 100644 index 451fe8d8117c..000000000000 --- a/extension/opampextension/internal/util/package_test.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package util - -import ( - "testing" - - "go.uber.org/goleak" -) - -func TestMain(m *testing.M) { - goleak.VerifyTestMain(m) -} diff --git a/extension/opampextension/internal/util/parse.go b/extension/opampextension/internal/util/parse.go deleted file mode 100644 index c52f64f3ac48..000000000000 --- a/extension/opampextension/internal/util/parse.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package util // import "github.com/open-telemetry/opentelemetry-collector-contrib/extension/opampextension/internal/util" - -import "strings" - -// ParseDarwinDescription parses out the OS name and version for darwin machines. -// 'input' should be the string representation from running the command 'sw_vers'. -// An example of this command's desired output is below: -// -// ProductName: macOS -// ProductVersion: 15.0.1 -// BuildVersion: 24A348 -func ParseDarwinDescription(input string) string { - var productName string - var productVersion string - for _, l := range strings.Split(input, "\n") { - line := strings.TrimSpace(l) - if raw, ok := strings.CutPrefix(line, "ProductName:"); ok { - productName = strings.TrimSpace(raw) - } else if raw, ok = strings.CutPrefix(line, "ProductVersion:"); ok { - productVersion = strings.TrimSpace(raw) - } - } - if productName != "" && productVersion != "" { - return productName + " " + productVersion - } - return "" -} - -// ParseLinuxDescription parses out the OS name and version for linux machines. -// 'input' should be the string representation from running the command 'lsb_release -d'. -// An example of this command's desired output is below: -// -// Description: Ubuntu 20.04.6 LTS -func ParseLinuxDescription(input string) string { - if raw, ok := strings.CutPrefix(strings.TrimSpace(input), "Description:"); ok { - return strings.TrimSpace(raw) - } - return "" -} - -// ParseLinuxDescription parses out the OS name and version for windows machines. -// 'input' should be the string representation from running the command 'cmd /c ver'. -// An example of this command's desired output is below: -// -// Microsoft Windows [Version 10.0.20348.2700] -func ParseWindowsDescription(input string) string { - return strings.TrimSpace(input) -} diff --git a/extension/opampextension/internal/util/parse_test.go b/extension/opampextension/internal/util/parse_test.go deleted file mode 100644 index 19ce49213848..000000000000 --- a/extension/opampextension/internal/util/parse_test.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package util - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestParseDarwinDescription(t *testing.T) { - testCases := []struct { - desc string - input string - expected string - }{ - { - desc: "basic use case", - input: "ProductName: macOS\nProductVersion: 15.0.1\nBuildVersion: 24A348", - expected: "macOS 15.0.1", - }, - { - desc: "excessive white space", - input: " \n ProductName: macOS\nProductVersion: 15.0.1 \n \n BuildVersion: 24A348\n", - expected: "macOS 15.0.1", - }, - { - desc: "random ordering & excessive white space", - input: "\nProductVersion: 15.0.1 \n \n BuildVersion: 24A348\n \n ProductName: macOS", - expected: "macOS 15.0.1", - }, - { - desc: "blank input", - input: "", - expected: "", - }, - { - desc: "missing ProductVersion", - input: "ProductName: macOS\nBuildVersion: 24A348", - expected: "", - }, - { - desc: "missing ProductName", - input: "ProductVersion: 15.0.1\nBuildVersion: 24A348", - expected: "", - }, - } - - for _, tc := range testCases { - t.Run(tc.desc, func(t *testing.T) { - actual := ParseDarwinDescription(tc.input) - require.Equal(t, tc.expected, actual) - }) - } -} - -func TestParseLinuxDescription(t *testing.T) { - testCases := []struct { - desc string - input string - expected string - }{ - { - desc: "basic use case", - input: "Description: Ubuntu 20.04.6 LTS", - expected: "Ubuntu 20.04.6 LTS", - }, - { - desc: "excessive white space", - input: " \n Description: Ubuntu 20.04.6 LTS \n ", - expected: "Ubuntu 20.04.6 LTS", - }, - { - desc: "blank input", - input: "", - expected: "", - }, - { - desc: "missing Description", - input: "Foo: Ubuntu 20.04.6 LTS", - expected: "", - }, - } - - for _, tc := range testCases { - t.Run(tc.desc, func(t *testing.T) { - actual := ParseLinuxDescription(tc.input) - require.Equal(t, tc.expected, actual) - }) - } -} - -func TestParseWindowsDescription(t *testing.T) { - testCases := []struct { - desc string - input string - expected string - }{ - { - desc: "basic use case", - input: "Microsoft Windows [Version 10.0.20348.2700]", - expected: "Microsoft Windows [Version 10.0.20348.2700]", - }, - { - desc: "excessive surrounding white space", - input: " \n Microsoft Windows [Version 10.0.20348.2700] \n ", - expected: "Microsoft Windows [Version 10.0.20348.2700]", - }, - { - desc: "excessive white space", - input: " \n Microsoft Windows [Version 10.0.20348.2700] \n ", - expected: "Microsoft Windows [Version 10.0.20348.2700]", - }, - { - desc: "blank input", - input: "", - expected: "", - }, - } - - for _, tc := range testCases { - t.Run(tc.desc, func(t *testing.T) { - actual := ParseWindowsDescription(tc.input) - require.Equal(t, tc.expected, actual) - }) - } -} diff --git a/extension/opampextension/opamp_agent.go b/extension/opampextension/opamp_agent.go index f3159d86edd9..b4afd6bcd6d6 100644 --- a/extension/opampextension/opamp_agent.go +++ b/extension/opampextension/opamp_agent.go @@ -9,7 +9,6 @@ import ( "fmt" "net/http" "os" - "os/exec" "runtime" "sort" "strings" @@ -27,10 +26,12 @@ import ( semconv "go.opentelemetry.io/collector/semconv/v1.27.0" "go.uber.org/zap" "golang.org/x/exp/maps" + "golang.org/x/text/cases" + "golang.org/x/text/language" "gopkg.in/yaml.v3" "github.com/open-telemetry/opentelemetry-collector-contrib/extension/opampcustommessages" - "github.com/open-telemetry/opentelemetry-collector-contrib/extension/opampextension/internal/util" + "github.com/shirou/gopsutil/v4/host" ) type opampAgent struct { @@ -255,9 +256,7 @@ func (o *opampAgent) createAgentDescription() error { nonIdentifyingAttributeMap[semconv.AttributeOSType] = runtime.GOOS nonIdentifyingAttributeMap[semconv.AttributeHostArch] = runtime.GOARCH nonIdentifyingAttributeMap[semconv.AttributeHostName] = hostname - if description != "" { - nonIdentifyingAttributeMap[semconv.AttributeOSDescription] = description - } + nonIdentifyingAttributeMap[semconv.AttributeOSDescription] = description for k, v := range o.cfg.AgentDescription.NonIdentifyingAttributes { nonIdentifyingAttributeMap[k] = v @@ -328,29 +327,19 @@ func (o *opampAgent) onMessage(_ context.Context, msg *types.MessageData) { } func getOSDescription(logger *zap.Logger) string { + info, err := host.Info() + if err != nil { + logger.Error("failed getting host info", zap.Error(err)) + return runtime.GOOS + } switch runtime.GOOS { case "darwin": - output, err := exec.Command("sw_vers").Output() - if err != nil { - logger.Error("get darwin OS details using 'sw_vers'", zap.Error(err)) - return "" - } - return util.ParseDarwinDescription(string(output)) + return "macOS " + info.PlatformVersion case "linux": - output, err := exec.Command("lsb_release", "-d").Output() - if err != nil { - logger.Error("get linux OS details using 'lsb_release -d'", zap.Error(err)) - return "" - } - return util.ParseLinuxDescription(string(output)) + return cases.Title(language.English).String(info.Platform) + " " + info.PlatformVersion case "windows": - output, err := exec.Command("cmd", "/c", "ver").Output() - if err != nil { - logger.Error("get windows OS details using 'cmd /c ver'", zap.Error(err)) - return "" - } - return util.ParseWindowsDescription(string(output)) + return info.Platform + " " + info.PlatformVersion + default: + return runtime.GOOS } - logger.Error("unrecognized OS to parse details from") - return "" } diff --git a/extension/opampextension/opamp_agent_test.go b/extension/opampextension/opamp_agent_test.go index 2078cda691ac..02f39984c047 100644 --- a/extension/opampextension/opamp_agent_test.go +++ b/extension/opampextension/opamp_agent_test.go @@ -53,7 +53,7 @@ func TestNewOpampAgentAttributes(t *testing.T) { func TestCreateAgentDescription(t *testing.T) { hostname, err := os.Hostname() require.NoError(t, err) - osDescription := getOSDescription(zap.NewNop()) + description := getOSDescription(zap.NewNop()) serviceName := "otelcol-distrot" serviceVersion := "distro.0" @@ -63,28 +63,23 @@ func TestCreateAgentDescription(t *testing.T) { name string cfg func(*Config) - expected func() *protobufs.AgentDescription + expected *protobufs.AgentDescription }{ { name: "No extra attributes", cfg: func(_ *Config) {}, - expected: func() *protobufs.AgentDescription { - ad := &protobufs.AgentDescription{ - IdentifyingAttributes: []*protobufs.KeyValue{ - stringKeyValue(semconv.AttributeServiceInstanceID, serviceInstanceUUID), - stringKeyValue(semconv.AttributeServiceName, serviceName), - stringKeyValue(semconv.AttributeServiceVersion, serviceVersion), - }, - NonIdentifyingAttributes: []*protobufs.KeyValue{ - stringKeyValue(semconv.AttributeHostArch, runtime.GOARCH), - stringKeyValue(semconv.AttributeHostName, hostname), - stringKeyValue(semconv.AttributeOSType, runtime.GOOS), - }, - } - if osDescription != "" { - ad.NonIdentifyingAttributes = append(ad.NonIdentifyingAttributes, stringKeyValue(semconv.AttributeOSDescription, osDescription)) - } - return ad + expected: &protobufs.AgentDescription{ + IdentifyingAttributes: []*protobufs.KeyValue{ + stringKeyValue(semconv.AttributeServiceInstanceID, serviceInstanceUUID), + stringKeyValue(semconv.AttributeServiceName, serviceName), + stringKeyValue(semconv.AttributeServiceVersion, serviceVersion), + }, + NonIdentifyingAttributes: []*protobufs.KeyValue{ + stringKeyValue(semconv.AttributeHostArch, runtime.GOARCH), + stringKeyValue(semconv.AttributeHostName, hostname), + stringKeyValue(semconv.AttributeOSDescription, description), + stringKeyValue(semconv.AttributeOSType, runtime.GOOS), + }, }, }, { @@ -95,25 +90,20 @@ func TestCreateAgentDescription(t *testing.T) { semconv.AttributeK8SPodName: "my-very-cool-pod", } }, - expected: func() *protobufs.AgentDescription { - ad := &protobufs.AgentDescription{ - IdentifyingAttributes: []*protobufs.KeyValue{ - stringKeyValue(semconv.AttributeServiceInstanceID, serviceInstanceUUID), - stringKeyValue(semconv.AttributeServiceName, serviceName), - stringKeyValue(semconv.AttributeServiceVersion, serviceVersion), - }, - NonIdentifyingAttributes: []*protobufs.KeyValue{ - stringKeyValue("env", "prod"), - stringKeyValue(semconv.AttributeHostArch, runtime.GOARCH), - stringKeyValue(semconv.AttributeHostName, hostname), - stringKeyValue(semconv.AttributeK8SPodName, "my-very-cool-pod"), - stringKeyValue(semconv.AttributeOSType, runtime.GOOS), - }, - } - if osDescription != "" { - ad.NonIdentifyingAttributes = append(ad.NonIdentifyingAttributes, stringKeyValue(semconv.AttributeOSDescription, osDescription)) - } - return ad + expected: &protobufs.AgentDescription{ + IdentifyingAttributes: []*protobufs.KeyValue{ + stringKeyValue(semconv.AttributeServiceInstanceID, serviceInstanceUUID), + stringKeyValue(semconv.AttributeServiceName, serviceName), + stringKeyValue(semconv.AttributeServiceVersion, serviceVersion), + }, + NonIdentifyingAttributes: []*protobufs.KeyValue{ + stringKeyValue("env", "prod"), + stringKeyValue(semconv.AttributeHostArch, runtime.GOARCH), + stringKeyValue(semconv.AttributeHostName, hostname), + stringKeyValue(semconv.AttributeK8SPodName, "my-very-cool-pod"), + stringKeyValue(semconv.AttributeOSDescription, description), + stringKeyValue(semconv.AttributeOSType, runtime.GOOS), + }, }, }, { @@ -123,23 +113,18 @@ func TestCreateAgentDescription(t *testing.T) { semconv.AttributeHostName: "override-host", } }, - expected: func() *protobufs.AgentDescription { - ad := &protobufs.AgentDescription{ - IdentifyingAttributes: []*protobufs.KeyValue{ - stringKeyValue(semconv.AttributeServiceInstanceID, serviceInstanceUUID), - stringKeyValue(semconv.AttributeServiceName, serviceName), - stringKeyValue(semconv.AttributeServiceVersion, serviceVersion), - }, - NonIdentifyingAttributes: []*protobufs.KeyValue{ - stringKeyValue(semconv.AttributeHostArch, runtime.GOARCH), - stringKeyValue(semconv.AttributeHostName, "override-host"), - stringKeyValue(semconv.AttributeOSType, runtime.GOOS), - }, - } - if osDescription != "" { - ad.NonIdentifyingAttributes = append(ad.NonIdentifyingAttributes, stringKeyValue(semconv.AttributeOSDescription, osDescription)) - } - return ad + expected: &protobufs.AgentDescription{ + IdentifyingAttributes: []*protobufs.KeyValue{ + stringKeyValue(semconv.AttributeServiceInstanceID, serviceInstanceUUID), + stringKeyValue(semconv.AttributeServiceName, serviceName), + stringKeyValue(semconv.AttributeServiceVersion, serviceVersion), + }, + NonIdentifyingAttributes: []*protobufs.KeyValue{ + stringKeyValue(semconv.AttributeHostArch, runtime.GOARCH), + stringKeyValue(semconv.AttributeHostName, "override-host"), + stringKeyValue(semconv.AttributeOSDescription, description), + stringKeyValue(semconv.AttributeOSType, runtime.GOOS), + }, }, }, } @@ -161,9 +146,7 @@ func TestCreateAgentDescription(t *testing.T) { err = o.createAgentDescription() assert.NoError(t, err) - expectedAD := tc.expected() - require.ElementsMatch(t, expectedAD.IdentifyingAttributes, o.agentDescription.IdentifyingAttributes) - require.ElementsMatch(t, expectedAD.NonIdentifyingAttributes, o.agentDescription.NonIdentifyingAttributes) + require.Equal(t, tc.expected, o.agentDescription) }) } }