-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
config.go
157 lines (135 loc) · 4.55 KB
/
config.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
149
150
151
152
153
154
155
156
157
// 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.
package config
import (
"encoding/json"
"fmt"
"html"
"net/http"
"strings"
"go.uber.org/fx"
"gopkg.in/yaml.v2"
coreconfig "github.com/DataDog/datadog-agent/comp/core/config"
apiutil "github.com/DataDog/datadog-agent/pkg/api/util"
pkgconfig "github.com/DataDog/datadog-agent/pkg/config"
"github.com/DataDog/datadog-agent/pkg/config/model"
traceconfig "github.com/DataDog/datadog-agent/pkg/trace/config"
"github.com/DataDog/datadog-agent/pkg/util/log"
"github.com/DataDog/datadog-agent/pkg/util/scrubber"
)
// team: agent-apm
type dependencies struct {
fx.In
Params Params
Config coreconfig.Component
}
// cfg implements the Component.
type cfg struct {
// this component is currently implementing a thin wrapper around pkg/trace/config,
// and uses globals in that package.
*traceconfig.AgentConfig
// coreConfig relates to the main agent config component
coreConfig coreconfig.Component
// warnings are the warnings generated during setup
warnings *pkgconfig.Warnings
}
func newConfig(deps dependencies) (Component, error) {
tracecfg, err := setupConfig(deps, "")
if err != nil {
// Allow main Agent to start with missing API key
if !(err == traceconfig.ErrMissingAPIKey && !deps.Params.FailIfAPIKeyMissing) {
return nil, err
}
}
c := cfg{
AgentConfig: tracecfg,
coreConfig: deps.Config,
}
c.SetMaxMemCPU(pkgconfig.IsContainerized())
return &c, nil
}
func (c *cfg) Warnings() *pkgconfig.Warnings {
return c.warnings
}
func (c *cfg) Object() *traceconfig.AgentConfig {
return c.AgentConfig
}
// SetHandler returns a handler to change the runtime configuration.
func (c *cfg) SetHandler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodPost {
httpError(w, http.StatusMethodNotAllowed, fmt.Errorf("%s method not allowed, only %s", req.Method, http.MethodPost))
return
}
for key, values := range req.URL.Query() {
if len(values) == 0 {
continue
}
value := html.UnescapeString(values[len(values)-1])
switch key {
case "log_level":
lvl := strings.ToLower(value)
if lvl == "warning" {
lvl = "warn"
}
if err := pkgconfig.ChangeLogLevel(lvl); err != nil {
httpError(w, http.StatusInternalServerError, err)
return
}
pkgconfig.Datadog.Set("log_level", lvl, model.SourceAgentRuntime)
log.Infof("Switched log level to %s", lvl)
default:
log.Infof("Unsupported config change requested (key: %q).", key)
}
}
})
}
// GetConfigHandler returns handler to get the runtime configuration.
func (c *cfg) GetConfigHandler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodGet {
httpError(w,
http.StatusMethodNotAllowed,
fmt.Errorf("%s method not allowed, only %s", req.Method, http.MethodGet),
)
return
}
if apiutil.Validate(w, req) != nil {
return
}
runtimeConfig, err := yaml.Marshal(c.coreConfig.AllSettings())
if err != nil {
log.Errorf("Unable to marshal runtime config response: %s", err)
body, _ := json.Marshal(map[string]string{"error": err.Error()})
http.Error(w, string(body), http.StatusInternalServerError)
return
}
scrubbed, err := scrubber.ScrubYaml(runtimeConfig)
if err != nil {
log.Errorf("Unable to get the core config: %s", err)
body, _ := json.Marshal(map[string]string{"error": err.Error()})
http.Error(w, string(body), http.StatusInternalServerError)
return
}
_, _ = w.Write(scrubbed)
})
}
// SetMaxMemCPU sets watchdog's max_memory and max_cpu_percent parameters.
// If the agent is containerized, max_memory and max_cpu_percent are disabled by default.
// Resource limits are better handled by container runtimes and orchestrators.
func (c *cfg) SetMaxMemCPU(isContainerized bool) {
if c.coreConfig.Object().IsSet("apm_config.max_cpu_percent") {
c.MaxCPU = c.coreConfig.Object().GetFloat64("apm_config.max_cpu_percent") / 100
} else if isContainerized {
log.Debug("Running in a container and apm_config.max_cpu_percent is not set, setting it to 0")
c.MaxCPU = 0
}
if c.coreConfig.Object().IsSet("apm_config.max_memory") {
c.MaxMemory = c.coreConfig.Object().GetFloat64("apm_config.max_memory")
} else if isContainerized {
log.Debug("Running in a container and apm_config.max_memory is not set, setting it to 0")
c.MaxMemory = 0
}
}