2015-08-20 04:03:56 -07:00
|
|
|
// Copyright 2015 The Prometheus Authors
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2013-01-07 14:24:26 -08:00
|
|
|
package config
|
|
|
|
|
|
|
|
import (
|
2022-05-23 00:54:32 -07:00
|
|
|
"errors"
|
2013-01-07 14:24:26 -08:00
|
|
|
"fmt"
|
2015-06-22 13:35:19 -07:00
|
|
|
"net/url"
|
2021-03-25 14:28:58 -07:00
|
|
|
"os"
|
2015-08-05 09:04:34 -07:00
|
|
|
"path/filepath"
|
2015-04-20 03:24:25 -07:00
|
|
|
"strings"
|
2013-01-07 14:24:26 -08:00
|
|
|
"time"
|
2014-12-10 08:46:56 -08:00
|
|
|
|
2021-05-15 19:19:22 -07:00
|
|
|
"github.com/alecthomas/units"
|
2021-06-11 09:17:59 -07:00
|
|
|
"github.com/go-kit/log"
|
|
|
|
"github.com/go-kit/log/level"
|
2022-02-12 15:58:27 -08:00
|
|
|
"github.com/grafana/regexp"
|
2020-08-20 05:48:26 -07:00
|
|
|
"github.com/prometheus/common/config"
|
2015-08-20 08:18:46 -07:00
|
|
|
"github.com/prometheus/common/model"
|
2021-08-26 06:37:19 -07:00
|
|
|
"github.com/prometheus/common/sigv4"
|
2022-08-31 06:50:38 -07:00
|
|
|
"gopkg.in/yaml.v2"
|
2019-03-25 16:01:12 -07:00
|
|
|
|
2020-08-20 05:48:26 -07:00
|
|
|
"github.com/prometheus/prometheus/discovery"
|
2021-11-08 06:23:17 -08:00
|
|
|
"github.com/prometheus/prometheus/model/labels"
|
|
|
|
"github.com/prometheus/prometheus/model/relabel"
|
2013-01-07 14:24:26 -08:00
|
|
|
)
|
|
|
|
|
2015-05-13 02:28:04 -07:00
|
|
|
var (
|
2021-02-18 04:12:21 -08:00
|
|
|
patRulePath = regexp.MustCompile(`^[^*]*(\*[^/]*)?$`)
|
|
|
|
reservedHeaders = map[string]struct{}{
|
2021-02-04 13:18:13 -08:00
|
|
|
// NOTE: authorization is checked specially,
|
|
|
|
// see RemoteWriteConfig.UnmarshalYAML.
|
|
|
|
// "authorization": {},
|
|
|
|
"host": {},
|
|
|
|
"content-encoding": {},
|
2021-02-18 04:12:21 -08:00
|
|
|
"content-length": {},
|
2021-02-04 13:18:13 -08:00
|
|
|
"content-type": {},
|
|
|
|
"user-agent": {},
|
|
|
|
"connection": {},
|
|
|
|
"keep-alive": {},
|
|
|
|
"proxy-authenticate": {},
|
|
|
|
"proxy-authorization": {},
|
|
|
|
"www-authenticate": {},
|
2021-02-18 04:12:21 -08:00
|
|
|
"accept-encoding": {},
|
|
|
|
"x-prometheus-remote-write-version": {},
|
|
|
|
"x-prometheus-remote-read-version": {},
|
2021-03-08 11:20:09 -08:00
|
|
|
|
|
|
|
// Added by SigV4.
|
|
|
|
"x-amz-date": {},
|
|
|
|
"x-amz-security-token": {},
|
|
|
|
"x-amz-content-sha256": {},
|
2021-02-04 13:18:13 -08:00
|
|
|
}
|
2015-05-13 02:28:04 -07:00
|
|
|
)
|
2013-01-07 14:24:26 -08:00
|
|
|
|
2015-05-07 01:55:03 -07:00
|
|
|
// Load parses the YAML input s into a Config.
|
2021-03-25 14:28:58 -07:00
|
|
|
func Load(s string, expandExternalLabels bool, logger log.Logger) (*Config, error) {
|
2015-06-23 10:40:44 -07:00
|
|
|
cfg := &Config{}
|
2015-07-17 07:12:33 -07:00
|
|
|
// If the entire config body is empty the UnmarshalYAML method is
|
|
|
|
// never called. We thus have to set the DefaultConfig at the entry
|
|
|
|
// point as well.
|
|
|
|
*cfg = DefaultConfig
|
|
|
|
|
2018-04-04 01:07:39 -07:00
|
|
|
err := yaml.UnmarshalStrict([]byte(s), cfg)
|
2015-05-07 01:55:03 -07:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-03-25 14:28:58 -07:00
|
|
|
|
|
|
|
if !expandExternalLabels {
|
|
|
|
return cfg, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, v := range cfg.GlobalConfig.ExternalLabels {
|
|
|
|
newV := os.Expand(v.Value, func(s string) string {
|
2022-01-17 07:43:55 -08:00
|
|
|
if s == "$" {
|
|
|
|
return "$"
|
|
|
|
}
|
2021-03-25 14:28:58 -07:00
|
|
|
if v := os.Getenv(s); v != "" {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
level.Warn(logger).Log("msg", "Empty environment variable", "name", s)
|
|
|
|
return ""
|
|
|
|
})
|
|
|
|
if newV != v.Value {
|
|
|
|
level.Debug(logger).Log("msg", "External label replaced", "label", v.Name, "input", v.Value, "output", newV)
|
|
|
|
v.Value = newV
|
|
|
|
cfg.GlobalConfig.ExternalLabels[i] = v
|
|
|
|
}
|
|
|
|
}
|
2015-05-07 01:55:03 -07:00
|
|
|
return cfg, nil
|
2013-01-07 14:24:26 -08:00
|
|
|
}
|
|
|
|
|
2015-08-05 09:30:37 -07:00
|
|
|
// LoadFile parses the given YAML file into a Config.
|
2021-10-22 01:06:44 -07:00
|
|
|
func LoadFile(filename string, agentMode, expandExternalLabels bool, logger log.Logger) (*Config, error) {
|
2022-04-27 02:24:36 -07:00
|
|
|
content, err := os.ReadFile(filename)
|
2015-05-07 01:55:03 -07:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-03-25 14:28:58 -07:00
|
|
|
cfg, err := Load(string(content), expandExternalLabels, logger)
|
2015-08-05 09:04:34 -07:00
|
|
|
if err != nil {
|
2022-05-23 00:54:32 -07:00
|
|
|
return nil, fmt.Errorf("parsing YAML file %s: %w", filename, err)
|
2015-08-05 09:04:34 -07:00
|
|
|
}
|
2021-10-29 16:41:40 -07:00
|
|
|
|
|
|
|
if agentMode {
|
|
|
|
if len(cfg.RemoteWriteConfigs) == 0 {
|
|
|
|
return nil, errors.New("at least one remote_write target must be specified in agent mode")
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(cfg.AlertingConfig.AlertmanagerConfigs) > 0 || len(cfg.AlertingConfig.AlertRelabelConfigs) > 0 {
|
|
|
|
return nil, errors.New("field alerting is not allowed in agent mode")
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(cfg.RuleFiles) > 0 {
|
|
|
|
return nil, errors.New("field rule_files is not allowed in agent mode")
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(cfg.RemoteReadConfigs) > 0 {
|
|
|
|
return nil, errors.New("field remote_read is not allowed in agent mode")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-20 05:48:26 -07:00
|
|
|
cfg.SetDirectory(filepath.Dir(filename))
|
2015-08-05 09:04:34 -07:00
|
|
|
return cfg, nil
|
2013-01-07 14:24:26 -08:00
|
|
|
}
|
|
|
|
|
2015-05-07 01:55:03 -07:00
|
|
|
// The defaults applied before parsing the respective config sections.
|
|
|
|
var (
|
2015-08-24 06:07:27 -07:00
|
|
|
// DefaultConfig is the default top-level configuration.
|
2015-06-04 08:03:12 -07:00
|
|
|
DefaultConfig = Config{
|
2015-06-07 08:40:22 -07:00
|
|
|
GlobalConfig: DefaultGlobalConfig,
|
2013-04-30 11:20:14 -07:00
|
|
|
}
|
2015-05-07 01:55:03 -07:00
|
|
|
|
2015-08-24 06:07:27 -07:00
|
|
|
// DefaultGlobalConfig is the default global configuration.
|
2015-06-04 08:03:12 -07:00
|
|
|
DefaultGlobalConfig = GlobalConfig{
|
2016-01-29 06:23:11 -08:00
|
|
|
ScrapeInterval: model.Duration(1 * time.Minute),
|
|
|
|
ScrapeTimeout: model.Duration(10 * time.Second),
|
|
|
|
EvaluationInterval: model.Duration(1 * time.Minute),
|
2013-01-07 14:24:26 -08:00
|
|
|
}
|
|
|
|
|
2015-08-24 06:07:27 -07:00
|
|
|
// DefaultScrapeConfig is the default scrape configuration.
|
2015-06-04 08:03:12 -07:00
|
|
|
DefaultScrapeConfig = ScrapeConfig{
|
2015-05-07 01:55:03 -07:00
|
|
|
// ScrapeTimeout and ScrapeInterval default to the
|
|
|
|
// configured globals.
|
2021-02-26 13:48:06 -08:00
|
|
|
MetricsPath: "/metrics",
|
|
|
|
Scheme: "http",
|
|
|
|
HonorLabels: false,
|
|
|
|
HonorTimestamps: true,
|
|
|
|
HTTPClientConfig: config.DefaultHTTPClientConfig,
|
2015-04-20 03:24:25 -07:00
|
|
|
}
|
2015-05-07 01:55:03 -07:00
|
|
|
|
2016-11-25 02:04:33 -08:00
|
|
|
// DefaultAlertmanagerConfig is the default alertmanager configuration.
|
|
|
|
DefaultAlertmanagerConfig = AlertmanagerConfig{
|
2021-02-26 13:48:06 -08:00
|
|
|
Scheme: "http",
|
|
|
|
Timeout: model.Duration(10 * time.Second),
|
2021-03-19 10:19:12 -07:00
|
|
|
APIVersion: AlertmanagerAPIVersionV2,
|
2021-02-26 13:48:06 -08:00
|
|
|
HTTPClientConfig: config.DefaultHTTPClientConfig,
|
2016-11-23 03:41:19 -08:00
|
|
|
}
|
|
|
|
|
2016-09-19 13:47:51 -07:00
|
|
|
// DefaultRemoteWriteConfig is the default remote write configuration.
|
|
|
|
DefaultRemoteWriteConfig = RemoteWriteConfig{
|
2021-02-26 13:48:06 -08:00
|
|
|
RemoteTimeout: model.Duration(30 * time.Second),
|
|
|
|
QueueConfig: DefaultQueueConfig,
|
|
|
|
MetadataConfig: DefaultMetadataConfig,
|
|
|
|
HTTPClientConfig: config.DefaultHTTPClientConfig,
|
2017-07-25 05:47:34 -07:00
|
|
|
}
|
|
|
|
|
2017-08-01 03:00:40 -07:00
|
|
|
// DefaultQueueConfig is the default remote queue configuration.
|
|
|
|
DefaultQueueConfig = QueueConfig{
|
2020-09-09 13:00:23 -07:00
|
|
|
// With a maximum of 200 shards, assuming an average of 100ms remote write
|
|
|
|
// time and 500 samples per batch, we will be able to push 1M samples/s.
|
|
|
|
MaxShards: 200,
|
2018-12-04 09:32:14 -08:00
|
|
|
MinShards: 1,
|
2020-09-09 13:00:23 -07:00
|
|
|
MaxSamplesPerSend: 500,
|
2017-07-25 05:47:34 -07:00
|
|
|
|
2020-09-09 13:00:23 -07:00
|
|
|
// Each shard will have a max of 2500 samples pending in its channel, plus the pending
|
|
|
|
// samples that have been enqueued. Theoretically we should only ever have about 3000 samples
|
|
|
|
// per shard pending. At 200 shards that's 600k.
|
|
|
|
Capacity: 2500,
|
2018-08-24 07:55:21 -07:00
|
|
|
BatchSendDeadline: model.Duration(5 * time.Second),
|
2017-07-25 05:47:34 -07:00
|
|
|
|
2019-06-10 12:43:08 -07:00
|
|
|
// Backoff times for retrying a batch of samples on recoverable errors.
|
2018-08-24 07:55:21 -07:00
|
|
|
MinBackoff: model.Duration(30 * time.Millisecond),
|
2021-11-09 14:08:24 -08:00
|
|
|
MaxBackoff: model.Duration(5 * time.Second),
|
2016-09-19 13:47:51 -07:00
|
|
|
}
|
2017-03-10 03:53:27 -08:00
|
|
|
|
2020-11-19 07:23:03 -08:00
|
|
|
// DefaultMetadataConfig is the default metadata configuration for a remote write endpoint.
|
|
|
|
DefaultMetadataConfig = MetadataConfig{
|
2021-06-24 15:39:50 -07:00
|
|
|
Send: true,
|
|
|
|
SendInterval: model.Duration(1 * time.Minute),
|
|
|
|
MaxSamplesPerSend: 500,
|
2020-11-19 07:23:03 -08:00
|
|
|
}
|
|
|
|
|
2017-03-10 03:53:27 -08:00
|
|
|
// DefaultRemoteReadConfig is the default remote read configuration.
|
|
|
|
DefaultRemoteReadConfig = RemoteReadConfig{
|
2022-02-16 13:12:47 -08:00
|
|
|
RemoteTimeout: model.Duration(1 * time.Minute),
|
|
|
|
HTTPClientConfig: config.DefaultHTTPClientConfig,
|
|
|
|
FilterExternalLabels: true,
|
2017-03-10 03:53:27 -08:00
|
|
|
}
|
2021-07-19 21:52:57 -07:00
|
|
|
|
|
|
|
// DefaultStorageConfig is the default TSDB/Exemplar storage configuration.
|
|
|
|
DefaultStorageConfig = StorageConfig{
|
|
|
|
ExemplarsConfig: &DefaultExemplarsConfig,
|
|
|
|
}
|
|
|
|
|
|
|
|
DefaultExemplarsConfig = ExemplarsConfig{
|
|
|
|
MaxExemplars: 100000,
|
|
|
|
}
|
2015-05-07 01:55:03 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
// Config is the top-level configuration for Prometheus's config files.
|
|
|
|
type Config struct {
|
2016-08-09 04:09:36 -07:00
|
|
|
GlobalConfig GlobalConfig `yaml:"global"`
|
|
|
|
AlertingConfig AlertingConfig `yaml:"alerting,omitempty"`
|
|
|
|
RuleFiles []string `yaml:"rule_files,omitempty"`
|
|
|
|
ScrapeConfigs []*ScrapeConfig `yaml:"scrape_configs,omitempty"`
|
2021-07-19 21:52:57 -07:00
|
|
|
StorageConfig StorageConfig `yaml:"storage,omitempty"`
|
2022-01-25 02:08:04 -08:00
|
|
|
TracingConfig TracingConfig `yaml:"tracing,omitempty"`
|
2015-05-07 01:55:03 -07:00
|
|
|
|
2017-02-13 12:43:20 -08:00
|
|
|
RemoteWriteConfigs []*RemoteWriteConfig `yaml:"remote_write,omitempty"`
|
2017-03-10 03:53:27 -08:00
|
|
|
RemoteReadConfigs []*RemoteReadConfig `yaml:"remote_read,omitempty"`
|
2015-05-07 01:55:03 -07:00
|
|
|
}
|
|
|
|
|
2020-08-20 05:48:26 -07:00
|
|
|
// SetDirectory joins any relative file paths with dir.
|
|
|
|
func (c *Config) SetDirectory(dir string) {
|
|
|
|
c.GlobalConfig.SetDirectory(dir)
|
|
|
|
c.AlertingConfig.SetDirectory(dir)
|
2022-01-29 14:56:44 -08:00
|
|
|
c.TracingConfig.SetDirectory(dir)
|
2020-08-20 05:48:26 -07:00
|
|
|
for i, file := range c.RuleFiles {
|
|
|
|
c.RuleFiles[i] = config.JoinDir(dir, file)
|
2016-11-24 06:17:50 -08:00
|
|
|
}
|
2020-08-20 05:48:26 -07:00
|
|
|
for _, c := range c.ScrapeConfigs {
|
|
|
|
c.SetDirectory(dir)
|
2015-08-05 09:04:34 -07:00
|
|
|
}
|
2020-08-20 05:48:26 -07:00
|
|
|
for _, c := range c.RemoteWriteConfigs {
|
|
|
|
c.SetDirectory(dir)
|
2019-03-12 03:24:15 -07:00
|
|
|
}
|
2020-08-20 05:48:26 -07:00
|
|
|
for _, c := range c.RemoteReadConfigs {
|
|
|
|
c.SetDirectory(dir)
|
2019-03-12 03:24:15 -07:00
|
|
|
}
|
2015-08-05 09:04:34 -07:00
|
|
|
}
|
|
|
|
|
2015-05-07 07:47:18 -07:00
|
|
|
func (c Config) String() string {
|
2017-05-29 04:46:23 -07:00
|
|
|
b, err := yaml.Marshal(c)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Sprintf("<error creating config string: %s>", err)
|
2013-01-07 14:24:26 -08:00
|
|
|
}
|
2017-05-29 04:46:23 -07:00
|
|
|
return string(b)
|
2015-05-07 01:55:03 -07:00
|
|
|
}
|
2013-04-30 11:20:14 -07:00
|
|
|
|
2015-05-27 18:12:42 -07:00
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
2015-05-07 01:55:03 -07:00
|
|
|
func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
2015-06-04 08:03:12 -07:00
|
|
|
*c = DefaultConfig
|
|
|
|
// We want to set c to the defaults and then overwrite it with the input.
|
|
|
|
// To make unmarshal fill the plain data struct rather than calling UnmarshalYAML
|
|
|
|
// again, we have to hide it using a type indirection.
|
|
|
|
type plain Config
|
|
|
|
if err := unmarshal((*plain)(c)); err != nil {
|
2015-05-07 01:55:03 -07:00
|
|
|
return err
|
|
|
|
}
|
2018-04-04 01:07:39 -07:00
|
|
|
|
2015-07-17 10:58:34 -07:00
|
|
|
// If a global block was open but empty the default global config is overwritten.
|
|
|
|
// We have to restore it here.
|
|
|
|
if c.GlobalConfig.isZero() {
|
|
|
|
c.GlobalConfig = DefaultGlobalConfig
|
|
|
|
}
|
|
|
|
|
2015-05-27 22:36:21 -07:00
|
|
|
for _, rf := range c.RuleFiles {
|
|
|
|
if !patRulePath.MatchString(rf) {
|
2022-05-23 00:54:32 -07:00
|
|
|
return fmt.Errorf("invalid rule file path %q", rf)
|
2015-05-27 22:36:21 -07:00
|
|
|
}
|
|
|
|
}
|
2015-05-07 01:55:03 -07:00
|
|
|
// Do global overrides and validate unique names.
|
2015-04-25 03:59:05 -07:00
|
|
|
jobNames := map[string]struct{}{}
|
2015-05-07 01:55:03 -07:00
|
|
|
for _, scfg := range c.ScrapeConfigs {
|
2018-12-03 02:09:02 -08:00
|
|
|
if scfg == nil {
|
2019-03-25 16:01:12 -07:00
|
|
|
return errors.New("empty or null scrape config section")
|
2018-12-03 02:09:02 -08:00
|
|
|
}
|
2016-02-15 02:08:49 -08:00
|
|
|
// First set the correct scrape interval, then check that the timeout
|
|
|
|
// (inferred or explicit) is not greater than that.
|
2015-05-07 01:55:03 -07:00
|
|
|
if scfg.ScrapeInterval == 0 {
|
|
|
|
scfg.ScrapeInterval = c.GlobalConfig.ScrapeInterval
|
|
|
|
}
|
2016-02-12 03:51:55 -08:00
|
|
|
if scfg.ScrapeTimeout > scfg.ScrapeInterval {
|
2022-05-23 00:54:32 -07:00
|
|
|
return fmt.Errorf("scrape timeout greater than scrape interval for scrape config with job name %q", scfg.JobName)
|
2016-02-12 03:51:55 -08:00
|
|
|
}
|
2016-02-15 02:08:49 -08:00
|
|
|
if scfg.ScrapeTimeout == 0 {
|
|
|
|
if c.GlobalConfig.ScrapeTimeout > scfg.ScrapeInterval {
|
|
|
|
scfg.ScrapeTimeout = scfg.ScrapeInterval
|
|
|
|
} else {
|
|
|
|
scfg.ScrapeTimeout = c.GlobalConfig.ScrapeTimeout
|
|
|
|
}
|
|
|
|
}
|
2013-01-07 14:24:26 -08:00
|
|
|
|
2015-05-07 01:55:03 -07:00
|
|
|
if _, ok := jobNames[scfg.JobName]; ok {
|
2022-05-23 00:54:32 -07:00
|
|
|
return fmt.Errorf("found multiple scrape configs with job name %q", scfg.JobName)
|
2013-02-22 12:07:35 -08:00
|
|
|
}
|
2015-05-07 01:55:03 -07:00
|
|
|
jobNames[scfg.JobName] = struct{}{}
|
2013-02-22 12:07:35 -08:00
|
|
|
}
|
2019-12-12 12:47:23 -08:00
|
|
|
rwNames := map[string]struct{}{}
|
2018-12-03 02:09:02 -08:00
|
|
|
for _, rwcfg := range c.RemoteWriteConfigs {
|
|
|
|
if rwcfg == nil {
|
2019-03-25 16:01:12 -07:00
|
|
|
return errors.New("empty or null remote write config section")
|
2018-12-03 02:09:02 -08:00
|
|
|
}
|
2019-12-12 12:47:23 -08:00
|
|
|
// Skip empty names, we fill their name with their config hash in remote write code.
|
|
|
|
if _, ok := rwNames[rwcfg.Name]; ok && rwcfg.Name != "" {
|
2022-05-23 00:54:32 -07:00
|
|
|
return fmt.Errorf("found multiple remote write configs with job name %q", rwcfg.Name)
|
2019-12-12 12:47:23 -08:00
|
|
|
}
|
|
|
|
rwNames[rwcfg.Name] = struct{}{}
|
2018-12-03 02:09:02 -08:00
|
|
|
}
|
2019-12-12 12:47:23 -08:00
|
|
|
rrNames := map[string]struct{}{}
|
2018-12-03 02:09:02 -08:00
|
|
|
for _, rrcfg := range c.RemoteReadConfigs {
|
|
|
|
if rrcfg == nil {
|
2019-03-25 16:01:12 -07:00
|
|
|
return errors.New("empty or null remote read config section")
|
2018-12-03 02:09:02 -08:00
|
|
|
}
|
2019-12-12 12:47:23 -08:00
|
|
|
// Skip empty names, we fill their name with their config hash in remote read code.
|
|
|
|
if _, ok := rrNames[rrcfg.Name]; ok && rrcfg.Name != "" {
|
2022-05-23 00:54:32 -07:00
|
|
|
return fmt.Errorf("found multiple remote read configs with job name %q", rrcfg.Name)
|
2019-12-12 12:47:23 -08:00
|
|
|
}
|
|
|
|
rrNames[rrcfg.Name] = struct{}{}
|
2018-12-03 02:09:02 -08:00
|
|
|
}
|
2016-06-12 07:18:05 -07:00
|
|
|
return nil
|
2013-02-22 12:07:35 -08:00
|
|
|
}
|
|
|
|
|
2015-05-07 07:47:18 -07:00
|
|
|
// GlobalConfig configures values that are used across other configuration
|
2015-05-07 01:55:03 -07:00
|
|
|
// objects.
|
|
|
|
type GlobalConfig struct {
|
|
|
|
// How frequently to scrape targets by default.
|
2016-01-29 06:23:11 -08:00
|
|
|
ScrapeInterval model.Duration `yaml:"scrape_interval,omitempty"`
|
2015-05-07 01:55:03 -07:00
|
|
|
// The default timeout when scraping targets.
|
2016-01-29 06:23:11 -08:00
|
|
|
ScrapeTimeout model.Duration `yaml:"scrape_timeout,omitempty"`
|
2015-05-07 01:55:03 -07:00
|
|
|
// How frequently to evaluate rules by default.
|
2016-01-29 06:23:11 -08:00
|
|
|
EvaluationInterval model.Duration `yaml:"evaluation_interval,omitempty"`
|
2020-01-08 05:28:43 -08:00
|
|
|
// File to which PromQL queries are logged.
|
|
|
|
QueryLogFile string `yaml:"query_log_file,omitempty"`
|
2015-05-07 01:55:03 -07:00
|
|
|
// The labels to add to any timeseries that this Prometheus instance scrapes.
|
2019-03-08 08:29:25 -08:00
|
|
|
ExternalLabels labels.Labels `yaml:"external_labels,omitempty"`
|
2013-01-07 14:24:26 -08:00
|
|
|
}
|
|
|
|
|
2020-08-20 05:48:26 -07:00
|
|
|
// SetDirectory joins any relative file paths with dir.
|
|
|
|
func (c *GlobalConfig) SetDirectory(dir string) {
|
|
|
|
c.QueryLogFile = config.JoinDir(dir, c.QueryLogFile)
|
|
|
|
}
|
|
|
|
|
2015-05-27 18:12:42 -07:00
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
2015-06-04 08:03:12 -07:00
|
|
|
func (c *GlobalConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
2016-02-15 05:08:25 -08:00
|
|
|
// Create a clean global config as the previous one was already populated
|
|
|
|
// by the default due to the YAML parser behavior for empty blocks.
|
|
|
|
gc := &GlobalConfig{}
|
|
|
|
type plain GlobalConfig
|
|
|
|
if err := unmarshal((*plain)(gc)); err != nil {
|
2015-05-07 01:55:03 -07:00
|
|
|
return err
|
|
|
|
}
|
2018-04-04 01:07:39 -07:00
|
|
|
|
2019-03-08 08:29:25 -08:00
|
|
|
for _, l := range gc.ExternalLabels {
|
|
|
|
if !model.LabelName(l.Name).IsValid() {
|
2022-05-23 00:54:32 -07:00
|
|
|
return fmt.Errorf("%q is not a valid label name", l.Name)
|
2019-03-08 08:29:25 -08:00
|
|
|
}
|
2019-03-14 14:16:29 -07:00
|
|
|
if !model.LabelValue(l.Value).IsValid() {
|
2022-05-23 00:54:32 -07:00
|
|
|
return fmt.Errorf("%q is not a valid label value", l.Value)
|
2019-03-14 14:16:29 -07:00
|
|
|
}
|
2019-03-08 08:29:25 -08:00
|
|
|
}
|
|
|
|
|
2016-02-15 02:08:49 -08:00
|
|
|
// First set the correct scrape interval, then check that the timeout
|
|
|
|
// (inferred or explicit) is not greater than that.
|
2016-02-15 05:08:25 -08:00
|
|
|
if gc.ScrapeInterval == 0 {
|
|
|
|
gc.ScrapeInterval = DefaultGlobalConfig.ScrapeInterval
|
2016-02-15 02:08:49 -08:00
|
|
|
}
|
2016-02-15 05:08:25 -08:00
|
|
|
if gc.ScrapeTimeout > gc.ScrapeInterval {
|
2019-03-25 16:01:12 -07:00
|
|
|
return errors.New("global scrape timeout greater than scrape interval")
|
2016-02-15 02:08:49 -08:00
|
|
|
}
|
2016-02-15 05:08:25 -08:00
|
|
|
if gc.ScrapeTimeout == 0 {
|
|
|
|
if DefaultGlobalConfig.ScrapeTimeout > gc.ScrapeInterval {
|
|
|
|
gc.ScrapeTimeout = gc.ScrapeInterval
|
2016-02-15 02:08:49 -08:00
|
|
|
} else {
|
2016-02-15 05:08:25 -08:00
|
|
|
gc.ScrapeTimeout = DefaultGlobalConfig.ScrapeTimeout
|
2016-02-15 02:08:49 -08:00
|
|
|
}
|
|
|
|
}
|
2016-02-15 05:08:25 -08:00
|
|
|
if gc.EvaluationInterval == 0 {
|
|
|
|
gc.EvaluationInterval = DefaultGlobalConfig.EvaluationInterval
|
2016-02-15 02:08:49 -08:00
|
|
|
}
|
2016-02-15 05:08:25 -08:00
|
|
|
*c = *gc
|
2016-06-12 07:18:05 -07:00
|
|
|
return nil
|
2013-01-07 14:24:26 -08:00
|
|
|
}
|
2013-08-16 09:17:48 -07:00
|
|
|
|
2015-07-17 10:58:34 -07:00
|
|
|
// isZero returns true iff the global config is the zero value.
|
|
|
|
func (c *GlobalConfig) isZero() bool {
|
2015-09-29 08:51:03 -07:00
|
|
|
return c.ExternalLabels == nil &&
|
2015-07-17 10:58:34 -07:00
|
|
|
c.ScrapeInterval == 0 &&
|
|
|
|
c.ScrapeTimeout == 0 &&
|
2020-01-08 05:28:43 -08:00
|
|
|
c.EvaluationInterval == 0 &&
|
|
|
|
c.QueryLogFile == ""
|
2015-07-17 10:58:34 -07:00
|
|
|
}
|
|
|
|
|
2016-11-23 03:41:19 -08:00
|
|
|
// ScrapeConfig configures a scraping unit for Prometheus.
|
|
|
|
type ScrapeConfig struct {
|
|
|
|
// The job name to which the job label is set by default.
|
|
|
|
JobName string `yaml:"job_name"`
|
|
|
|
// Indicator whether the scraped metrics should remain unmodified.
|
|
|
|
HonorLabels bool `yaml:"honor_labels,omitempty"`
|
2019-03-15 03:04:15 -07:00
|
|
|
// Indicator whether the scraped timestamps should be respected.
|
|
|
|
HonorTimestamps bool `yaml:"honor_timestamps"`
|
2016-11-23 03:41:19 -08:00
|
|
|
// A set of query parameters with which the target is scraped.
|
|
|
|
Params url.Values `yaml:"params,omitempty"`
|
|
|
|
// How frequently to scrape the targets of this scrape config.
|
|
|
|
ScrapeInterval model.Duration `yaml:"scrape_interval,omitempty"`
|
|
|
|
// The timeout for scraping targets of this config.
|
|
|
|
ScrapeTimeout model.Duration `yaml:"scrape_timeout,omitempty"`
|
|
|
|
// The HTTP resource path on which to fetch metrics from targets.
|
|
|
|
MetricsPath string `yaml:"metrics_path,omitempty"`
|
|
|
|
// The URL scheme with which to fetch metrics from targets.
|
|
|
|
Scheme string `yaml:"scheme,omitempty"`
|
2021-05-15 19:19:22 -07:00
|
|
|
// An uncompressed response body larger than this many bytes will cause the
|
|
|
|
// scrape to fail. 0 means no limit.
|
|
|
|
BodySizeLimit units.Base2Bytes `yaml:"body_size_limit,omitempty"`
|
2021-05-06 01:56:21 -07:00
|
|
|
// More than this many samples post metric-relabeling will cause the scrape to
|
|
|
|
// fail.
|
2016-12-16 07:08:50 -08:00
|
|
|
SampleLimit uint `yaml:"sample_limit,omitempty"`
|
2020-07-30 05:20:24 -07:00
|
|
|
// More than this many targets after the target relabeling will cause the
|
|
|
|
// scrapes to fail.
|
|
|
|
TargetLimit uint `yaml:"target_limit,omitempty"`
|
2021-05-06 01:56:21 -07:00
|
|
|
// More than this many labels post metric-relabeling will cause the scrape to
|
|
|
|
// fail.
|
|
|
|
LabelLimit uint `yaml:"label_limit,omitempty"`
|
|
|
|
// More than this label name length post metric-relabeling will cause the
|
|
|
|
// scrape to fail.
|
|
|
|
LabelNameLengthLimit uint `yaml:"label_name_length_limit,omitempty"`
|
|
|
|
// More than this label value length post metric-relabeling will cause the
|
|
|
|
// scrape to fail.
|
|
|
|
LabelValueLengthLimit uint `yaml:"label_value_length_limit,omitempty"`
|
2016-11-23 03:41:19 -08:00
|
|
|
|
|
|
|
// We cannot do proper Go type embedding below as the parser will then parse
|
|
|
|
// values arbitrarily into the overflow maps of further-down types.
|
|
|
|
|
2020-08-20 05:48:26 -07:00
|
|
|
ServiceDiscoveryConfigs discovery.Configs `yaml:"-"`
|
|
|
|
HTTPClientConfig config.HTTPClientConfig `yaml:",inline"`
|
2016-11-23 03:41:19 -08:00
|
|
|
|
2015-06-12 14:16:13 -07:00
|
|
|
// List of target relabel configurations.
|
2018-12-18 03:26:36 -08:00
|
|
|
RelabelConfigs []*relabel.Config `yaml:"relabel_configs,omitempty"`
|
2015-06-12 14:16:13 -07:00
|
|
|
// List of metric relabel configurations.
|
2018-12-18 03:26:36 -08:00
|
|
|
MetricRelabelConfigs []*relabel.Config `yaml:"metric_relabel_configs,omitempty"`
|
2013-08-16 09:17:48 -07:00
|
|
|
}
|
2015-04-20 03:24:25 -07:00
|
|
|
|
2020-08-20 05:48:26 -07:00
|
|
|
// SetDirectory joins any relative file paths with dir.
|
|
|
|
func (c *ScrapeConfig) SetDirectory(dir string) {
|
|
|
|
c.ServiceDiscoveryConfigs.SetDirectory(dir)
|
|
|
|
c.HTTPClientConfig.SetDirectory(dir)
|
|
|
|
}
|
|
|
|
|
2015-06-04 08:03:12 -07:00
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
|
|
|
func (c *ScrapeConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
|
|
*c = DefaultScrapeConfig
|
2020-08-20 05:48:26 -07:00
|
|
|
if err := discovery.UnmarshalYAMLWithInlineConfigs(c, unmarshal); err != nil {
|
2015-06-04 08:03:12 -07:00
|
|
|
return err
|
|
|
|
}
|
2016-09-14 23:00:14 -07:00
|
|
|
if len(c.JobName) == 0 {
|
2019-03-25 16:01:12 -07:00
|
|
|
return errors.New("job_name is empty")
|
2015-06-04 08:03:12 -07:00
|
|
|
}
|
2016-11-24 06:17:50 -08:00
|
|
|
|
2016-11-23 03:41:19 -08:00
|
|
|
// The UnmarshalYAML method of HTTPClientConfig is not being called because it's not a pointer.
|
|
|
|
// We cannot make it a pointer as the parser panics for inlined pointer structs.
|
|
|
|
// Thus we just do its validation here.
|
2018-04-04 01:07:39 -07:00
|
|
|
if err := c.HTTPClientConfig.Validate(); err != nil {
|
2016-11-24 06:17:50 -08:00
|
|
|
return err
|
2015-07-22 08:48:22 -07:00
|
|
|
}
|
2016-11-23 03:41:19 -08:00
|
|
|
|
2015-11-07 06:25:51 -08:00
|
|
|
// Check for users putting URLs in target groups.
|
|
|
|
if len(c.RelabelConfigs) == 0 {
|
2020-08-20 05:48:26 -07:00
|
|
|
if err := checkStaticTargets(c.ServiceDiscoveryConfigs); err != nil {
|
|
|
|
return err
|
2015-11-07 06:25:51 -08:00
|
|
|
}
|
|
|
|
}
|
2018-06-13 08:34:59 -07:00
|
|
|
|
2018-12-03 02:09:02 -08:00
|
|
|
for _, rlcfg := range c.RelabelConfigs {
|
|
|
|
if rlcfg == nil {
|
2019-03-25 16:01:12 -07:00
|
|
|
return errors.New("empty or null target relabeling rule in scrape config")
|
2018-12-03 02:09:02 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, rlcfg := range c.MetricRelabelConfigs {
|
|
|
|
if rlcfg == nil {
|
2019-03-25 16:01:12 -07:00
|
|
|
return errors.New("empty or null metric relabeling rule in scrape config")
|
2018-12-03 02:09:02 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-12 07:18:05 -07:00
|
|
|
return nil
|
2015-06-04 08:03:12 -07:00
|
|
|
}
|
|
|
|
|
2020-08-20 05:48:26 -07:00
|
|
|
// MarshalYAML implements the yaml.Marshaler interface.
|
|
|
|
func (c *ScrapeConfig) MarshalYAML() (interface{}, error) {
|
|
|
|
return discovery.MarshalYAMLWithInlineConfigs(c)
|
|
|
|
}
|
|
|
|
|
2021-07-19 21:52:57 -07:00
|
|
|
// StorageConfig configures runtime reloadable configuration options.
|
|
|
|
type StorageConfig struct {
|
2022-09-20 10:05:50 -07:00
|
|
|
TSDBConfig *TSDBConfig `yaml:"tsdb,omitempty"`
|
2021-07-19 21:52:57 -07:00
|
|
|
ExemplarsConfig *ExemplarsConfig `yaml:"exemplars,omitempty"`
|
|
|
|
}
|
|
|
|
|
2022-09-20 10:05:50 -07:00
|
|
|
// TSDBConfig configures runtime reloadable configuration options.
|
|
|
|
type TSDBConfig struct {
|
|
|
|
// OutOfOrderTimeWindow sets how long back in time an out-of-order sample can be inserted
|
|
|
|
// into the TSDB. This flag is typically set while unmarshaling the configuration file and translating
|
|
|
|
// OutOfOrderTimeWindowFlag's duration. The unit of this flag is expected to be the same as any
|
|
|
|
// other timestamp in the TSDB.
|
|
|
|
OutOfOrderTimeWindow int64
|
|
|
|
|
|
|
|
// OutOfOrderTimeWindowFlag holds the parsed duration from the config file.
|
|
|
|
// During unmarshall, this is converted into milliseconds and stored in OutOfOrderTimeWindow.
|
|
|
|
// This should not be used directly and must be converted into OutOfOrderTimeWindow.
|
|
|
|
OutOfOrderTimeWindowFlag model.Duration `yaml:"out_of_order_time_window,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
|
|
|
func (t *TSDBConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
|
|
*t = TSDBConfig{}
|
|
|
|
type plain TSDBConfig
|
|
|
|
if err := unmarshal((*plain)(t)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
t.OutOfOrderTimeWindow = time.Duration(t.OutOfOrderTimeWindowFlag).Milliseconds()
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-01-25 02:08:04 -08:00
|
|
|
type TracingClientType string
|
|
|
|
|
|
|
|
const (
|
|
|
|
TracingClientHTTP TracingClientType = "http"
|
|
|
|
TracingClientGRPC TracingClientType = "grpc"
|
2022-02-22 08:07:30 -08:00
|
|
|
|
|
|
|
GzipCompression = "gzip"
|
2022-01-25 02:08:04 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
|
|
|
func (t *TracingClientType) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
|
|
*t = TracingClientType("")
|
|
|
|
type plain TracingClientType
|
|
|
|
if err := unmarshal((*plain)(t)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if *t != TracingClientHTTP && *t != TracingClientGRPC {
|
|
|
|
return fmt.Errorf("expected tracing client type to be to be %s or %s, but got %s",
|
|
|
|
TracingClientHTTP, TracingClientGRPC, *t,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// TracingConfig configures the tracing options.
|
|
|
|
type TracingConfig struct {
|
|
|
|
ClientType TracingClientType `yaml:"client_type,omitempty"`
|
|
|
|
Endpoint string `yaml:"endpoint,omitempty"`
|
|
|
|
SamplingFraction float64 `yaml:"sampling_fraction,omitempty"`
|
2022-01-29 14:56:44 -08:00
|
|
|
Insecure bool `yaml:"insecure,omitempty"`
|
2022-01-25 02:08:04 -08:00
|
|
|
TLSConfig config.TLSConfig `yaml:"tls_config,omitempty"`
|
2022-02-22 08:07:30 -08:00
|
|
|
Headers map[string]string `yaml:"headers,omitempty"`
|
|
|
|
Compression string `yaml:"compression,omitempty"`
|
|
|
|
Timeout model.Duration `yaml:"timeout,omitempty"`
|
2022-01-25 02:08:04 -08:00
|
|
|
}
|
|
|
|
|
2022-01-29 14:56:44 -08:00
|
|
|
// SetDirectory joins any relative file paths with dir.
|
|
|
|
func (t *TracingConfig) SetDirectory(dir string) {
|
|
|
|
t.TLSConfig.SetDirectory(dir)
|
|
|
|
}
|
|
|
|
|
2022-01-25 02:08:04 -08:00
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
|
|
|
func (t *TracingConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
2022-01-29 14:56:44 -08:00
|
|
|
*t = TracingConfig{
|
|
|
|
ClientType: TracingClientGRPC,
|
|
|
|
}
|
2022-01-25 02:08:04 -08:00
|
|
|
type plain TracingConfig
|
|
|
|
if err := unmarshal((*plain)(t)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-02-22 12:44:36 -08:00
|
|
|
if err := validateHeadersForTracing(t.Headers); err != nil {
|
2022-02-22 08:07:30 -08:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-01-25 02:08:04 -08:00
|
|
|
if t.Endpoint == "" {
|
|
|
|
return errors.New("tracing endpoint must be set")
|
|
|
|
}
|
|
|
|
|
2022-02-22 08:07:30 -08:00
|
|
|
if t.Compression != "" && t.Compression != GzipCompression {
|
|
|
|
return fmt.Errorf("invalid compression type %s provided, valid options: %s",
|
|
|
|
t.Compression, GzipCompression)
|
|
|
|
}
|
|
|
|
|
2022-01-25 02:08:04 -08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-07-19 21:52:57 -07:00
|
|
|
// ExemplarsConfig configures runtime reloadable configuration options.
|
|
|
|
type ExemplarsConfig struct {
|
|
|
|
// MaxExemplars sets the size, in # of exemplars stored, of the single circular buffer used to store exemplars in memory.
|
|
|
|
// Use a value of 0 or less than 0 to disable the storage without having to restart Prometheus.
|
|
|
|
MaxExemplars int64 `yaml:"max_exemplars,omitempty"`
|
|
|
|
}
|
|
|
|
|
2016-11-25 02:04:33 -08:00
|
|
|
// AlertingConfig configures alerting and alertmanager related configs.
|
2016-11-23 03:41:19 -08:00
|
|
|
type AlertingConfig struct {
|
2019-12-12 08:00:19 -08:00
|
|
|
AlertRelabelConfigs []*relabel.Config `yaml:"alert_relabel_configs,omitempty"`
|
|
|
|
AlertmanagerConfigs AlertmanagerConfigs `yaml:"alertmanagers,omitempty"`
|
2016-11-23 03:41:19 -08:00
|
|
|
}
|
|
|
|
|
2020-08-20 05:48:26 -07:00
|
|
|
// SetDirectory joins any relative file paths with dir.
|
|
|
|
func (c *AlertingConfig) SetDirectory(dir string) {
|
|
|
|
for _, c := range c.AlertmanagerConfigs {
|
|
|
|
c.SetDirectory(dir)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-23 03:41:19 -08:00
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
|
|
|
func (c *AlertingConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
|
|
// Create a clean global config as the previous one was already populated
|
|
|
|
// by the default due to the YAML parser behavior for empty blocks.
|
|
|
|
*c = AlertingConfig{}
|
|
|
|
type plain AlertingConfig
|
2018-12-03 02:09:02 -08:00
|
|
|
if err := unmarshal((*plain)(c)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, rlcfg := range c.AlertRelabelConfigs {
|
|
|
|
if rlcfg == nil {
|
2019-03-25 16:01:12 -07:00
|
|
|
return errors.New("empty or null alert relabeling rule")
|
2018-12-03 02:09:02 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
2016-11-23 03:41:19 -08:00
|
|
|
}
|
|
|
|
|
2019-12-12 08:00:19 -08:00
|
|
|
// AlertmanagerConfigs is a slice of *AlertmanagerConfig.
|
|
|
|
type AlertmanagerConfigs []*AlertmanagerConfig
|
|
|
|
|
|
|
|
// ToMap converts a slice of *AlertmanagerConfig to a map.
|
|
|
|
func (a AlertmanagerConfigs) ToMap() map[string]*AlertmanagerConfig {
|
|
|
|
ret := make(map[string]*AlertmanagerConfig)
|
|
|
|
for i := range a {
|
|
|
|
ret[fmt.Sprintf("config-%d", i)] = a[i]
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
2019-04-18 05:17:03 -07:00
|
|
|
// AlertmanagerAPIVersion represents a version of the
|
|
|
|
// github.com/prometheus/alertmanager/api, e.g. 'v1' or 'v2'.
|
|
|
|
type AlertmanagerAPIVersion string
|
|
|
|
|
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
|
|
|
func (v *AlertmanagerAPIVersion) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
|
|
*v = AlertmanagerAPIVersion("")
|
|
|
|
type plain AlertmanagerAPIVersion
|
|
|
|
if err := unmarshal((*plain)(v)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, supportedVersion := range SupportedAlertmanagerAPIVersions {
|
|
|
|
if *v == supportedVersion {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmt.Errorf("expected Alertmanager api version to be one of %v but got %v", SupportedAlertmanagerAPIVersions, *v)
|
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
// AlertmanagerAPIVersionV1 represents
|
|
|
|
// github.com/prometheus/alertmanager/api/v1.
|
|
|
|
AlertmanagerAPIVersionV1 AlertmanagerAPIVersion = "v1"
|
|
|
|
// AlertmanagerAPIVersionV2 represents
|
|
|
|
// github.com/prometheus/alertmanager/api/v2.
|
|
|
|
AlertmanagerAPIVersionV2 AlertmanagerAPIVersion = "v2"
|
|
|
|
)
|
|
|
|
|
|
|
|
var SupportedAlertmanagerAPIVersions = []AlertmanagerAPIVersion{
|
|
|
|
AlertmanagerAPIVersionV1, AlertmanagerAPIVersionV2,
|
|
|
|
}
|
|
|
|
|
2017-03-18 14:32:08 -07:00
|
|
|
// AlertmanagerConfig configures how Alertmanagers can be discovered and communicated with.
|
2016-11-24 06:17:50 -08:00
|
|
|
type AlertmanagerConfig struct {
|
2016-11-23 03:42:33 -08:00
|
|
|
// We cannot do proper Go type embedding below as the parser will then parse
|
|
|
|
// values arbitrarily into the overflow maps of further-down types.
|
|
|
|
|
2020-08-20 05:48:26 -07:00
|
|
|
ServiceDiscoveryConfigs discovery.Configs `yaml:"-"`
|
|
|
|
HTTPClientConfig config.HTTPClientConfig `yaml:",inline"`
|
2016-11-23 03:42:33 -08:00
|
|
|
|
|
|
|
// The URL scheme to use when talking to Alertmanagers.
|
|
|
|
Scheme string `yaml:"scheme,omitempty"`
|
|
|
|
// Path prefix to add in front of the push endpoint path.
|
|
|
|
PathPrefix string `yaml:"path_prefix,omitempty"`
|
|
|
|
// The timeout used when sending alerts.
|
2018-08-24 07:55:21 -07:00
|
|
|
Timeout model.Duration `yaml:"timeout,omitempty"`
|
2016-11-23 03:42:33 -08:00
|
|
|
|
2019-04-18 05:17:03 -07:00
|
|
|
// The api version of Alertmanager.
|
|
|
|
APIVersion AlertmanagerAPIVersion `yaml:"api_version"`
|
|
|
|
|
2016-11-23 03:42:33 -08:00
|
|
|
// List of Alertmanager relabel configurations.
|
2018-12-18 03:26:36 -08:00
|
|
|
RelabelConfigs []*relabel.Config `yaml:"relabel_configs,omitempty"`
|
2016-11-23 03:42:33 -08:00
|
|
|
}
|
|
|
|
|
2020-08-20 05:48:26 -07:00
|
|
|
// SetDirectory joins any relative file paths with dir.
|
|
|
|
func (c *AlertmanagerConfig) SetDirectory(dir string) {
|
|
|
|
c.ServiceDiscoveryConfigs.SetDirectory(dir)
|
|
|
|
c.HTTPClientConfig.SetDirectory(dir)
|
|
|
|
}
|
|
|
|
|
2016-11-23 03:42:33 -08:00
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
2016-11-24 06:17:50 -08:00
|
|
|
func (c *AlertmanagerConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
2016-11-25 02:04:33 -08:00
|
|
|
*c = DefaultAlertmanagerConfig
|
2020-08-20 05:48:26 -07:00
|
|
|
if err := discovery.UnmarshalYAMLWithInlineConfigs(c, unmarshal); err != nil {
|
2016-11-23 03:42:33 -08:00
|
|
|
return err
|
|
|
|
}
|
2016-11-24 06:17:50 -08:00
|
|
|
|
2016-11-23 03:42:33 -08:00
|
|
|
// The UnmarshalYAML method of HTTPClientConfig is not being called because it's not a pointer.
|
|
|
|
// We cannot make it a pointer as the parser panics for inlined pointer structs.
|
|
|
|
// Thus we just do its validation here.
|
Refactor SD configuration to remove `config` dependency (#3629)
* refactor: move targetGroup struct and CheckOverflow() to their own package
* refactor: move auth and security related structs to a utility package, fix import error in utility package
* refactor: Azure SD, remove SD struct from config
* refactor: DNS SD, remove SD struct from config into dns package
* refactor: ec2 SD, move SD struct from config into the ec2 package
* refactor: file SD, move SD struct from config to file discovery package
* refactor: gce, move SD struct from config to gce discovery package
* refactor: move HTTPClientConfig and URL into util/config, fix import error in httputil
* refactor: consul, move SD struct from config into consul discovery package
* refactor: marathon, move SD struct from config into marathon discovery package
* refactor: triton, move SD struct from config to triton discovery package, fix test
* refactor: zookeeper, move SD structs from config to zookeeper discovery package
* refactor: openstack, remove SD struct from config, move into openstack discovery package
* refactor: kubernetes, move SD struct from config into kubernetes discovery package
* refactor: notifier, use targetgroup package instead of config
* refactor: tests for file, marathon, triton SD - use targetgroup package instead of config.TargetGroup
* refactor: retrieval, use targetgroup package instead of config.TargetGroup
* refactor: storage, use config util package
* refactor: discovery manager, use targetgroup package instead of config.TargetGroup
* refactor: use HTTPClient and TLS config from configUtil instead of config
* refactor: tests, use targetgroup package instead of config.TargetGroup
* refactor: fix tagetgroup.Group pointers that were removed by mistake
* refactor: openstack, kubernetes: drop prefixes
* refactor: remove import aliases forced due to vscode bug
* refactor: move main SD struct out of config into discovery/config
* refactor: rename configUtil to config_util
* refactor: rename yamlUtil to yaml_config
* refactor: kubernetes, remove prefixes
* refactor: move the TargetGroup package to discovery/
* refactor: fix order of imports
2017-12-29 12:01:34 -08:00
|
|
|
if err := c.HTTPClientConfig.Validate(); err != nil {
|
2016-11-24 06:17:50 -08:00
|
|
|
return err
|
2016-11-23 03:42:33 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check for users putting URLs in target groups.
|
|
|
|
if len(c.RelabelConfigs) == 0 {
|
2020-08-20 05:48:26 -07:00
|
|
|
if err := checkStaticTargets(c.ServiceDiscoveryConfigs); err != nil {
|
|
|
|
return err
|
2016-11-23 03:42:33 -08:00
|
|
|
}
|
|
|
|
}
|
2018-06-13 08:34:59 -07:00
|
|
|
|
2018-12-03 02:09:02 -08:00
|
|
|
for _, rlcfg := range c.RelabelConfigs {
|
|
|
|
if rlcfg == nil {
|
2019-03-25 16:01:12 -07:00
|
|
|
return errors.New("empty or null Alertmanager target relabeling rule")
|
2018-12-03 02:09:02 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-20 05:48:26 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalYAML implements the yaml.Marshaler interface.
|
|
|
|
func (c *AlertmanagerConfig) MarshalYAML() (interface{}, error) {
|
|
|
|
return discovery.MarshalYAMLWithInlineConfigs(c)
|
|
|
|
}
|
2018-06-13 08:34:59 -07:00
|
|
|
|
2020-08-20 05:48:26 -07:00
|
|
|
func checkStaticTargets(configs discovery.Configs) error {
|
|
|
|
for _, cfg := range configs {
|
|
|
|
sc, ok := cfg.(discovery.StaticConfig)
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
for _, tg := range sc {
|
|
|
|
for _, t := range tg.Targets {
|
|
|
|
if err := CheckTargetAddress(t[model.AddressLabel]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-23 03:42:33 -08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-11-07 06:25:51 -08:00
|
|
|
// CheckTargetAddress checks if target address is valid.
|
|
|
|
func CheckTargetAddress(address model.LabelValue) error {
|
|
|
|
// For now check for a URL, we may want to expand this later.
|
|
|
|
if strings.Contains(string(address), "/") {
|
2022-05-23 00:54:32 -07:00
|
|
|
return fmt.Errorf("%q is not a valid hostname", address)
|
2015-11-07 06:25:51 -08:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-03-10 03:53:27 -08:00
|
|
|
// RemoteWriteConfig is the configuration for writing to remote storage.
|
2016-09-19 13:47:51 -07:00
|
|
|
type RemoteWriteConfig struct {
|
2020-08-20 05:48:26 -07:00
|
|
|
URL *config.URL `yaml:"url"`
|
2018-12-18 03:26:36 -08:00
|
|
|
RemoteTimeout model.Duration `yaml:"remote_timeout,omitempty"`
|
2021-02-04 13:18:13 -08:00
|
|
|
Headers map[string]string `yaml:"headers,omitempty"`
|
2018-12-18 03:26:36 -08:00
|
|
|
WriteRelabelConfigs []*relabel.Config `yaml:"write_relabel_configs,omitempty"`
|
2019-12-12 12:47:23 -08:00
|
|
|
Name string `yaml:"name,omitempty"`
|
2021-05-06 13:53:52 -07:00
|
|
|
SendExemplars bool `yaml:"send_exemplars,omitempty"`
|
2016-09-19 13:47:51 -07:00
|
|
|
|
2017-03-20 05:37:50 -07:00
|
|
|
// We cannot do proper Go type embedding below as the parser will then parse
|
|
|
|
// values arbitrarily into the overflow maps of further-down types.
|
2020-08-20 05:48:26 -07:00
|
|
|
HTTPClientConfig config.HTTPClientConfig `yaml:",inline"`
|
|
|
|
QueueConfig QueueConfig `yaml:"queue_config,omitempty"`
|
2020-11-19 07:23:03 -08:00
|
|
|
MetadataConfig MetadataConfig `yaml:"metadata_config,omitempty"`
|
2021-08-26 06:37:19 -07:00
|
|
|
SigV4Config *sigv4.SigV4Config `yaml:"sigv4,omitempty"`
|
2020-08-20 05:48:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// SetDirectory joins any relative file paths with dir.
|
|
|
|
func (c *RemoteWriteConfig) SetDirectory(dir string) {
|
|
|
|
c.HTTPClientConfig.SetDirectory(dir)
|
2016-09-19 13:47:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
|
|
|
func (c *RemoteWriteConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
|
|
*c = DefaultRemoteWriteConfig
|
|
|
|
type plain RemoteWriteConfig
|
|
|
|
if err := unmarshal((*plain)(c)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-08-07 00:49:45 -07:00
|
|
|
if c.URL == nil {
|
2019-03-25 16:01:12 -07:00
|
|
|
return errors.New("url for remote_write is empty")
|
2017-08-07 00:49:45 -07:00
|
|
|
}
|
2018-12-03 02:09:02 -08:00
|
|
|
for _, rlcfg := range c.WriteRelabelConfigs {
|
|
|
|
if rlcfg == nil {
|
2019-03-25 16:01:12 -07:00
|
|
|
return errors.New("empty or null relabeling rule in remote write config")
|
2018-12-03 02:09:02 -08:00
|
|
|
}
|
|
|
|
}
|
2021-02-18 04:12:21 -08:00
|
|
|
if err := validateHeaders(c.Headers); err != nil {
|
|
|
|
return err
|
2021-02-04 13:18:13 -08:00
|
|
|
}
|
2017-07-25 05:47:34 -07:00
|
|
|
|
|
|
|
// The UnmarshalYAML method of HTTPClientConfig is not being called because it's not a pointer.
|
|
|
|
// We cannot make it a pointer as the parser panics for inlined pointer structs.
|
|
|
|
// Thus we just do its validation here.
|
2021-03-08 11:20:09 -08:00
|
|
|
if err := c.HTTPClientConfig.Validate(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
httpClientConfigAuthEnabled := c.HTTPClientConfig.BasicAuth != nil ||
|
2021-04-28 05:47:52 -07:00
|
|
|
c.HTTPClientConfig.Authorization != nil || c.HTTPClientConfig.OAuth2 != nil
|
2021-03-08 11:20:09 -08:00
|
|
|
|
|
|
|
if httpClientConfigAuthEnabled && c.SigV4Config != nil {
|
2021-04-28 05:47:52 -07:00
|
|
|
return fmt.Errorf("at most one of basic_auth, authorization, oauth2, & sigv4 must be configured")
|
2021-03-08 11:20:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
2016-09-19 13:47:51 -07:00
|
|
|
}
|
2017-03-10 03:53:27 -08:00
|
|
|
|
2022-02-22 12:44:36 -08:00
|
|
|
func validateHeadersForTracing(headers map[string]string) error {
|
|
|
|
for header := range headers {
|
|
|
|
if strings.ToLower(header) == "authorization" {
|
|
|
|
return errors.New("custom authorization header configuration is not yet supported")
|
|
|
|
}
|
|
|
|
if _, ok := reservedHeaders[strings.ToLower(header)]; ok {
|
2022-05-23 00:54:32 -07:00
|
|
|
return fmt.Errorf("%s is a reserved header. It must not be changed", header)
|
2022-02-22 12:44:36 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-02-18 04:12:21 -08:00
|
|
|
func validateHeaders(headers map[string]string) error {
|
|
|
|
for header := range headers {
|
|
|
|
if strings.ToLower(header) == "authorization" {
|
2021-04-28 05:47:52 -07:00
|
|
|
return errors.New("authorization header must be changed via the basic_auth, authorization, oauth2, or sigv4 parameter")
|
2021-02-18 04:12:21 -08:00
|
|
|
}
|
|
|
|
if _, ok := reservedHeaders[strings.ToLower(header)]; ok {
|
2022-05-23 00:54:32 -07:00
|
|
|
return fmt.Errorf("%s is a reserved header. It must not be changed", header)
|
2021-02-18 04:12:21 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-08-01 03:00:40 -07:00
|
|
|
// QueueConfig is the configuration for the queue used to write to remote
|
2017-07-25 05:47:34 -07:00
|
|
|
// storage.
|
2017-08-01 03:00:40 -07:00
|
|
|
type QueueConfig struct {
|
2019-08-13 02:10:21 -07:00
|
|
|
// Number of samples to buffer per shard before we block. Defaults to
|
|
|
|
// MaxSamplesPerSend.
|
2017-08-01 03:00:40 -07:00
|
|
|
Capacity int `yaml:"capacity,omitempty"`
|
2017-07-25 05:47:34 -07:00
|
|
|
|
|
|
|
// Max number of shards, i.e. amount of concurrency.
|
2017-08-01 03:00:40 -07:00
|
|
|
MaxShards int `yaml:"max_shards,omitempty"`
|
2017-07-25 05:47:34 -07:00
|
|
|
|
2018-12-04 09:32:14 -08:00
|
|
|
// Min number of shards, i.e. amount of concurrency.
|
|
|
|
MinShards int `yaml:"min_shards,omitempty"`
|
|
|
|
|
2017-07-25 05:47:34 -07:00
|
|
|
// Maximum number of samples per send.
|
2017-08-01 03:00:40 -07:00
|
|
|
MaxSamplesPerSend int `yaml:"max_samples_per_send,omitempty"`
|
2017-07-25 05:47:34 -07:00
|
|
|
|
|
|
|
// Maximum time sample will wait in buffer.
|
2018-08-24 07:55:21 -07:00
|
|
|
BatchSendDeadline model.Duration `yaml:"batch_send_deadline,omitempty"`
|
2017-07-25 05:47:34 -07:00
|
|
|
|
|
|
|
// On recoverable errors, backoff exponentially.
|
2021-02-11 09:24:49 -08:00
|
|
|
MinBackoff model.Duration `yaml:"min_backoff,omitempty"`
|
|
|
|
MaxBackoff model.Duration `yaml:"max_backoff,omitempty"`
|
|
|
|
RetryOnRateLimit bool `yaml:"retry_on_http_429,omitempty"`
|
2017-07-25 05:47:34 -07:00
|
|
|
}
|
|
|
|
|
2020-11-19 07:23:03 -08:00
|
|
|
// MetadataConfig is the configuration for sending metadata to remote
|
|
|
|
// storage.
|
|
|
|
type MetadataConfig struct {
|
|
|
|
// Send controls whether we send metric metadata to remote storage.
|
|
|
|
Send bool `yaml:"send"`
|
|
|
|
// SendInterval controls how frequently we send metric metadata.
|
|
|
|
SendInterval model.Duration `yaml:"send_interval"`
|
2021-06-24 15:39:50 -07:00
|
|
|
// Maximum number of samples per send.
|
|
|
|
MaxSamplesPerSend int `yaml:"max_samples_per_send,omitempty"`
|
2020-11-19 07:23:03 -08:00
|
|
|
}
|
|
|
|
|
2017-03-10 03:53:27 -08:00
|
|
|
// RemoteReadConfig is the configuration for reading from remote storage.
|
|
|
|
type RemoteReadConfig struct {
|
2021-02-18 04:12:21 -08:00
|
|
|
URL *config.URL `yaml:"url"`
|
|
|
|
RemoteTimeout model.Duration `yaml:"remote_timeout,omitempty"`
|
|
|
|
Headers map[string]string `yaml:"headers,omitempty"`
|
|
|
|
ReadRecent bool `yaml:"read_recent,omitempty"`
|
|
|
|
Name string `yaml:"name,omitempty"`
|
2019-12-12 12:47:23 -08:00
|
|
|
|
2017-03-20 05:37:50 -07:00
|
|
|
// We cannot do proper Go type embedding below as the parser will then parse
|
|
|
|
// values arbitrarily into the overflow maps of further-down types.
|
2020-08-20 05:48:26 -07:00
|
|
|
HTTPClientConfig config.HTTPClientConfig `yaml:",inline"`
|
2017-03-10 03:53:27 -08:00
|
|
|
|
2017-11-11 17:23:20 -08:00
|
|
|
// RequiredMatchers is an optional list of equality matchers which have to
|
|
|
|
// be present in a selector to query the remote read endpoint.
|
|
|
|
RequiredMatchers model.LabelSet `yaml:"required_matchers,omitempty"`
|
2022-02-16 13:12:47 -08:00
|
|
|
|
|
|
|
// Whether to use the external labels as selectors for the remote read endpoint.
|
|
|
|
FilterExternalLabels bool `yaml:"filter_external_labels,omitempty"`
|
2017-03-10 03:53:27 -08:00
|
|
|
}
|
|
|
|
|
2020-08-20 05:48:26 -07:00
|
|
|
// SetDirectory joins any relative file paths with dir.
|
|
|
|
func (c *RemoteReadConfig) SetDirectory(dir string) {
|
|
|
|
c.HTTPClientConfig.SetDirectory(dir)
|
|
|
|
}
|
|
|
|
|
2017-03-10 03:53:27 -08:00
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
|
|
|
func (c *RemoteReadConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
|
|
*c = DefaultRemoteReadConfig
|
|
|
|
type plain RemoteReadConfig
|
|
|
|
if err := unmarshal((*plain)(c)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-08-07 00:49:45 -07:00
|
|
|
if c.URL == nil {
|
2019-03-25 16:01:12 -07:00
|
|
|
return errors.New("url for remote_read is empty")
|
2017-08-07 00:49:45 -07:00
|
|
|
}
|
2021-02-18 04:12:21 -08:00
|
|
|
if err := validateHeaders(c.Headers); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-07-25 05:47:34 -07:00
|
|
|
// The UnmarshalYAML method of HTTPClientConfig is not being called because it's not a pointer.
|
|
|
|
// We cannot make it a pointer as the parser panics for inlined pointer structs.
|
|
|
|
// Thus we just do its validation here.
|
2018-04-04 01:07:39 -07:00
|
|
|
return c.HTTPClientConfig.Validate()
|
2017-03-10 03:53:27 -08:00
|
|
|
}
|