-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
resources.go
148 lines (125 loc) · 4.4 KB
/
resources.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-present Datadog, Inc.
//go:build linux || darwin
package resourcesimpl
import (
"context"
"runtime"
"time"
"github.com/DataDog/datadog-agent/comp/core/config"
"github.com/DataDog/datadog-agent/comp/core/log"
"github.com/DataDog/datadog-agent/comp/metadata/resources"
"github.com/DataDog/datadog-agent/comp/metadata/runner/runnerimpl"
configUtils "github.com/DataDog/datadog-agent/pkg/config/utils"
"github.com/DataDog/datadog-agent/pkg/gohai/processes"
"github.com/DataDog/datadog-agent/pkg/serializer"
"github.com/DataDog/datadog-agent/pkg/util/hostname"
"go.uber.org/fx"
)
const defaultCollectInterval = 300 * time.Second
const providerName = "resources"
type resourcesImpl struct {
log log.Component
hostname string
collectInterval time.Duration
serializer serializer.MetricSerializer
}
type dependencies struct {
fx.In
// Resources is enabled by default for most binaries. But even for binaries where we don't want to send the
// 'resources' paylod, like dogstatsd, we still need the resources Component. This is because the resources data
// is embedded in other metadata payload like 'host'. This means that even if resources is disabled it might be
// required in the build in order for the `Get` method to be available.
//
// This is why we have a Params struct for resources. It's `optional` so most of the binaries don't have to
// supply a Params struct but only need to import the metadata.Bundle.
Params *Params `optional:"true"`
Log log.Component
Config config.Component
Serializer serializer.MetricSerializer
}
type provides struct {
fx.Out
Comp resources.Component
Provider runnerimpl.Provider
}
func newResourcesProvider(deps dependencies) provides {
// By default, the 'resources' metadata is only enabled on Linux. Users can manually enable it on darwin
// platform. This is legacy behavior from Agent V5.
enabled := runtime.GOOS == "linux"
collectInterval := defaultCollectInterval
confProviders, err := configUtils.GetMetadataProviders(deps.Config)
if err != nil {
deps.Log.Errorf("Error parsing metadata provider configuration, falling back to default behavior: %s", err)
} else {
for _, p := range confProviders {
if p.Name == providerName {
// user configured interval take precedence over the default one
collectInterval = p.Interval * time.Second
enabled = true
break
}
}
}
hname, _ := hostname.Get(context.Background())
r := resourcesImpl{
log: deps.Log,
hostname: hname,
collectInterval: collectInterval,
serializer: deps.Serializer,
}
res := provides{
Comp: &r,
}
if deps.Params != nil && deps.Params.Disabled {
deps.Log.Infof("resources metadata provider is not available for this binary")
} else if !enabled {
deps.Log.Infof("resources metadata provider is disabled from the configuration")
} else if collectInterval == 0 {
deps.Log.Infof("Collection interval for 'resources' metadata provider is set to 0: disabling it")
} else {
deps.Log.Debugf("Collection interval for 'resources' metadata provider is set to %s", collectInterval)
res.Provider = runnerimpl.NewProvider(r.collect)
}
return res
}
// For testing purposes
var collectResources = gohaiResourcesCollect
func gohaiResourcesCollect() (interface{}, error) {
info, err := processes.CollectInfo()
if err != nil {
return nil, err
}
processes, _, err := info.AsJSON()
return processes, err
}
// Get returns the resources payload to be used in other metadata providers.
func (r *resourcesImpl) Get() map[string]interface{} {
proc, err := collectResources()
if err != nil {
r.log.Warnf("Failed to retrieve processes metadata from gohai: %s", err)
return nil
}
// The format dates back from Agent V5
return map[string]interface{}{
"resources": map[string]interface{}{
"processes": map[string]interface{}{
"snaps": []interface{}{proc},
},
"meta": map[string]string{
"host": r.hostname,
},
},
}
}
func (r *resourcesImpl) collect(_ context.Context) time.Duration {
payload := r.Get()
if payload != nil {
if err := r.serializer.SendProcessesMetadata(payload); err != nil {
r.log.Errorf("unable to serialize processes metadata payload, %s", err)
}
}
return r.collectInterval
}