Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[system detector] Fallback to os.Hostname when FQDN is not available #3099

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@
package system

import (
"os"
"runtime"
"strings"

"github.com/Showmax/go-fqdn"
)

type systemMetadata interface {
// Hostname returns the OS hostname
Hostname() (string, error)

// FQDN returns the fully qualified domain name
FQDN() (string, error)

Expand All @@ -38,3 +42,7 @@ func (*systemMetadataImpl) OSType() (string, error) {
func (*systemMetadataImpl) FQDN() (string, error) {
return fqdn.FqdnHostname()
}

func (*systemMetadataImpl) Hostname() (string, error) {
return os.Hostname()
}
17 changes: 12 additions & 5 deletions processor/resourcedetectionprocessor/internal/system/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/consumer/pdata"
"go.opentelemetry.io/collector/translator/conventions"
"go.uber.org/zap"

"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal"
)
Expand All @@ -35,11 +36,12 @@ var _ internal.Detector = (*Detector)(nil)
// Detector is a system metadata detector
type Detector struct {
provider systemMetadata
logger *zap.Logger
}

// NewDetector creates a new system metadata detector
func NewDetector(component.ProcessorCreateParams, internal.DetectorConfig) (internal.Detector, error) {
return &Detector{provider: &systemMetadataImpl{}}, nil
func NewDetector(p component.ProcessorCreateParams, _ internal.DetectorConfig) (internal.Detector, error) {
return &Detector{provider: &systemMetadataImpl{}, logger: p.Logger}, nil
}

// Detect detects system metadata and returns a resource with the available ones
Expand All @@ -52,12 +54,17 @@ func (d *Detector) Detect(_ context.Context) (pdata.Resource, error) {
return res, fmt.Errorf("failed getting OS type: %w", err)
}

fqdn, err := d.provider.FQDN()
hostname, err := d.provider.FQDN()
if err != nil {
return res, fmt.Errorf("failed getting FQDN: %w", err)
// Fallback to OS hostname
d.logger.Debug("FQDN query failed, falling back to OS hostname", zap.Error(err))
hostname, err = d.provider.Hostname()
if err != nil {
return res, fmt.Errorf("failed getting OS hostname: %w", err)
}
}

attrs.InsertString(conventions.AttributeHostName, fqdn)
attrs.InsertString(conventions.AttributeHostName, hostname)
attrs.InsertString(conventions.AttributeOSType, osType)

return res, nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ type mockMetadata struct {
mock.Mock
}

func (m *mockMetadata) Hostname() (string, error) {
args := m.MethodCalled("Hostname")
return args.String(0), args.Error(1)
}

func (m *mockMetadata) FQDN() (string, error) {
args := m.MethodCalled("FQDN")
return args.String(0), args.Error(1)
Expand All @@ -54,7 +59,7 @@ func TestDetectFQDNAvailable(t *testing.T) {
md.On("FQDN").Return("fqdn", nil)
md.On("OSType").Return("DARWIN", nil)

detector := &Detector{provider: md}
detector := &Detector{provider: md, logger: zap.NewNop()}
res, err := detector.Detect(context.Background())
require.NoError(t, err)
md.AssertExpectations(t)
Expand All @@ -70,23 +75,45 @@ func TestDetectFQDNAvailable(t *testing.T) {

}

func TestFallbackHostname(t *testing.T) {
mdHostname := &mockMetadata{}
mdHostname.On("Hostname").Return("hostname", nil)
mdHostname.On("FQDN").Return("", errors.New("err"))
mdHostname.On("OSType").Return("DARWIN", nil)

detector := &Detector{provider: mdHostname, logger: zap.NewNop()}
res, err := detector.Detect(context.Background())
require.NoError(t, err)
mdHostname.AssertExpectations(t)
res.Attributes().Sort()

expected := internal.NewResource(map[string]interface{}{
conventions.AttributeHostName: "hostname",
conventions.AttributeOSType: "DARWIN",
})
expected.Attributes().Sort()

assert.Equal(t, expected, res)
}

func TestDetectError(t *testing.T) {
// FQDN fails
// FQDN and hostname fail
mdFQDN := &mockMetadata{}
mdFQDN.On("OSType").Return("WINDOWS", nil)
mdFQDN.On("FQDN").Return("", errors.New("err"))
mdFQDN.On("Hostname").Return("", errors.New("err"))

detector := &Detector{provider: mdFQDN}
detector := &Detector{provider: mdFQDN, logger: zap.NewNop()}
res, err := detector.Detect(context.Background())
assert.Error(t, err)
assert.True(t, internal.IsEmptyResource(res))

// Hostname fails
mdHostname := &mockMetadata{}
mdHostname.On("FQDN").Return("fqdn", nil)
mdHostname.On("OSType").Return("", errors.New("err"))
// OS type fails
mdOSType := &mockMetadata{}
mdOSType.On("FQDN").Return("fqdn", nil)
mdOSType.On("OSType").Return("", errors.New("err"))

detector = &Detector{provider: mdHostname}
detector = &Detector{provider: mdOSType, logger: zap.NewNop()}
res, err = detector.Detect(context.Background())
assert.Error(t, err)
assert.True(t, internal.IsEmptyResource(res))
Expand Down