Skip to content

Commit

Permalink
Share host info between packages
Browse files Browse the repository at this point in the history
  • Loading branch information
swiatekm committed Oct 31, 2024
1 parent 0cdfef5 commit ff85105
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 13 deletions.
32 changes: 32 additions & 0 deletions changelog/fragments/1730288427-shared-host.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Kind can be one of:
# - breaking-change: a change to previously-documented behavior
# - deprecation: functionality that is being removed in a later release
# - bug-fix: fixes a problem in a previous version
# - enhancement: extends functionality but does not break or fix existing behavior
# - feature: new functionality
# - known-issue: problems that we are aware of in a given version
# - security: impacts on the security of a product or a user’s deployment.
# - upgrade: important information for someone upgrading from a prior version
# - other: does not fit into any of the other categories
kind: enhancement

# Change summary; a 80ish characters long description of the change.
summary: Collect host info exactly once on startup

# Long description; in case the summary is not enough to describe the change
# this field accommodate a description without length limits.
# NOTE: This field will be rendered only for breaking-change and known-issue kinds at the moment.
#description:

# Affected component; usually one of "elastic-agent", "fleet-server", "filebeat", "metricbeat", "auditbeat", "all", etc.
component: elastic-agent

# PR URL; optional; the PR number that added the changeset.
# If not present is automatically filled by the tooling finding the PR where this changelog fragment has been added.
# NOTE: the tooling supports backports, so it's able to fill the original PR number instead of the backport PR number.
# Please provide it if you are adding a fragment for a different PR.
#pr: https://github.com/owner/repo/1234

# Issue URL; optional; the GitHub issue related to this changeset (either closes or is part of).
# If not present is automatically filled by the tooling with the issue linked to the PR number.
#issue: https://github.com/owner/repo/1234
5 changes: 2 additions & 3 deletions internal/pkg/agent/application/info/agent_metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"github.com/elastic/elastic-agent/internal/pkg/util"
"github.com/elastic/elastic-agent/pkg/core/logger"

"github.com/elastic/go-sysinfo"
"github.com/elastic/go-sysinfo/types"
)

Expand Down Expand Up @@ -146,7 +145,7 @@ func Metadata(ctx context.Context, l *logger.Logger) (*ECSMeta, error) {

// ECSMetadata returns an agent ECS compliant metadata.
func (i *AgentInfo) ECSMetadata(l *logger.Logger) (*ECSMeta, error) {
sysInfo, err := sysinfo.Host()
sysInfo, err := util.GetHost()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -195,7 +194,7 @@ func (i *AgentInfo) ECSMetadataFlatMap(l *logger.Logger) (map[string]interface{}
// TODO: remove these values when kibana migrates to ECS
meta := make(map[string]interface{})

sysInfo, err := sysinfo.Host()
sysInfo, err := util.GetHost()
if err != nil {
return nil, err
}
Expand Down
4 changes: 1 addition & 3 deletions internal/pkg/agent/application/info/agent_metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/elastic/go-sysinfo"

"github.com/elastic/elastic-agent/internal/pkg/agent/application/paths"
"github.com/elastic/elastic-agent/internal/pkg/release"
"github.com/elastic/elastic-agent/internal/pkg/testutils"
Expand All @@ -34,7 +32,7 @@ func TestECSMetadata(t *testing.T) {
assert.NotNil(t, metadata.Elastic.Agent, "metadata.Elastic.Agent must not be nil")
}

sysInfo, err := sysinfo.Host()
sysInfo, err := util.GetHost()
require.NoError(t, err)

info := sysInfo.Info()
Expand Down
5 changes: 3 additions & 2 deletions internal/pkg/agent/application/info/inject_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ package info
import (
"runtime"

"github.com/elastic/elastic-agent/internal/pkg/util"

"github.com/elastic/elastic-agent/internal/pkg/agent/application/paths"
"github.com/elastic/elastic-agent/internal/pkg/agent/errors"
"github.com/elastic/elastic-agent/internal/pkg/config"
"github.com/elastic/go-sysinfo"
)

// InjectAgentConfig injects config to a provided configuration.
Expand All @@ -30,7 +31,7 @@ func InjectAgentConfig(c *config.Config) error {
// agentGlobalConfig gets global config used for resolution of variables inside configuration
// such as ${path.data}.
func agentGlobalConfig() (map[string]interface{}, error) {
hostInfo, err := sysinfo.Host()
hostInfo, err := util.GetHost()
if err != nil {
return nil, err
}
Expand Down
1 change: 1 addition & 0 deletions internal/pkg/composable/providers/host/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ func ContextProviderBuilder(log *logger.Logger, c *config.Config, _ bool) (corec

func getHostInfo(log *logger.Logger) func() (map[string]interface{}, error) {
return func() (map[string]interface{}, error) {
// We don't use the shared host info from util here, as we explicitly want the latest host information on every call.
sysInfo, err := sysinfo.Host()
if err != nil {
return nil, err
Expand Down
60 changes: 60 additions & 0 deletions internal/pkg/util/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ package util

import (
"context"
"sync"
"time"

"github.com/elastic/elastic-agent/pkg/core/logger"
"github.com/elastic/go-sysinfo"
"github.com/elastic/go-sysinfo/types"
)

Expand All @@ -31,3 +33,61 @@ func GetHostName(isFqdnFeatureEnabled bool, hostInfo types.HostInfo, host types.

return fqdn
}

var _ types.Host = &threadSafeHost{}

// threadSafeHost is a thread-safe wrapper around types.Host.
// It exists so we can only create it once, as some of the setup it does is relatively expensive.
type threadSafeHost struct {
sync.Mutex
inner types.Host
}

func newThreadSafeHost(inner types.Host) *threadSafeHost {
return &threadSafeHost{inner: inner}
}

func (s *threadSafeHost) CPUTime() (types.CPUTimes, error) {
s.Lock()
defer s.Unlock()
return s.inner.CPUTime()
}

func (s *threadSafeHost) Info() types.HostInfo {
s.Lock()
defer s.Unlock()
return s.inner.Info()
}

func (s *threadSafeHost) Memory() (*types.HostMemoryInfo, error) {
s.Lock()
defer s.Unlock()
return s.inner.Memory()
}

func (s *threadSafeHost) FQDNWithContext(ctx context.Context) (string, error) {
s.Lock()
defer s.Unlock()
return s.inner.FQDNWithContext(ctx)
}

func (s *threadSafeHost) FQDN() (string, error) {
s.Lock()
defer s.Unlock()
return s.inner.FQDN()
}

var (
sharedHost types.Host
once sync.Once
hostErr error
)

func GetHost() (types.Host, error) {
once.Do(func() {
var innerHost types.Host
innerHost, hostErr = sysinfo.Host()
sharedHost = newThreadSafeHost(innerHost)
})
return sharedHost, hostErr
}
20 changes: 20 additions & 0 deletions internal/pkg/util/host_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/elastic/elastic-agent-libs/logp"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/elastic/go-sysinfo/types"
Expand Down Expand Up @@ -59,6 +60,25 @@ func TestGetHostName(t *testing.T) {
}
}

func TestSharedHost(t *testing.T) {
innerHost := &mockHost{}
shared := newThreadSafeHost(innerHost)

innerCpuTime, _ := innerHost.CPUTime()
sharedCpuTime, _ := shared.CPUTime()
assert.Equal(t, innerCpuTime, sharedCpuTime)

assert.Equal(t, innerHost.Info(), shared.Info())

innerMemoryInfo, _ := innerHost.Memory()
sharedMemoryInfo, _ := shared.Memory()
assert.Equal(t, innerMemoryInfo, sharedMemoryInfo)

innerFQDN, _ := innerHost.FQDN()
sharedFQDN, _ := shared.FQDN()
assert.Equal(t, innerFQDN, sharedFQDN)
}

type mockHost struct {
fqdn string
fqdnErr error
Expand Down
5 changes: 2 additions & 3 deletions pkg/component/platforms.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import (
goruntime "runtime"
"strings"

"github.com/elastic/go-sysinfo"

"github.com/elastic/elastic-agent/internal/pkg/util"
"github.com/elastic/elastic-agent/pkg/utils"
)

Expand Down Expand Up @@ -126,7 +125,7 @@ func LoadPlatformDetail(modifiers ...PlatformModifier) (PlatformDetail, error) {
if err != nil {
return PlatformDetail{}, err
}
info, err := sysinfo.Host()
info, err := util.GetHost()
if err != nil {
return PlatformDetail{}, err
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/testing/define/define.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ import (

"github.com/elastic/elastic-agent-libs/kibana"
"github.com/elastic/go-elasticsearch/v8"
"github.com/elastic/go-sysinfo"
"github.com/elastic/go-sysinfo/types"

"github.com/elastic/elastic-agent/internal/pkg/util"
atesting "github.com/elastic/elastic-agent/pkg/testing"
"github.com/elastic/elastic-agent/pkg/utils"
semver "github.com/elastic/elastic-agent/pkg/version"
Expand Down Expand Up @@ -205,7 +205,7 @@ func runOrSkip(t *testing.T, req Requirements, local bool, kubernetes bool) *Inf

func getOSInfo() (*types.OSInfo, error) {
osInfoOnce.Do(func() {
sysInfo, err := sysinfo.Host()
sysInfo, err := util.GetHost()
if err != nil {
osInfoErr = err
} else {
Expand Down

0 comments on commit ff85105

Please sign in to comment.