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"
2023-10-10 03:16:55 -07:00
"sort"
2024-04-01 08:34:35 -07:00
"strconv"
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"
2023-06-01 14:20:10 -07:00
"github.com/prometheus/prometheus/storage/remote/azuread"
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
}
2023-04-30 04:52:34 -07:00
b := labels . NewScratchBuilder ( 0 )
2022-03-09 14:26:05 -08:00
cfg . GlobalConfig . ExternalLabels . Range ( func ( v labels . Label ) {
2021-03-25 14:28:58 -07:00
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 )
}
2023-04-30 04:52:34 -07:00
// Note newV can be blank. https://github.com/prometheus/prometheus/issues/11024
2022-03-09 14:26:05 -08:00
b . Add ( v . Name , newV )
} )
cfg . GlobalConfig . ExternalLabels = b . Labels ( )
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 . 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 ) ,
2024-05-30 03:49:50 -07:00
RuleQueryOffset : model . Duration ( 0 * time . Minute ) ,
2023-10-10 03:16:55 -07:00
// When native histogram feature flag is enabled, ScrapeProtocols default
// changes to DefaultNativeHistogramScrapeProtocols.
ScrapeProtocols : DefaultScrapeProtocols ,
2013-01-07 14:24:26 -08:00
}
2024-04-01 08:34:35 -07:00
DefaultRuntimeConfig = RuntimeConfig {
// Go runtime tuning.
2024-06-10 00:34:55 -07:00
GoGC : 75 ,
2024-04-01 08:34:35 -07: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 {
2023-10-10 03:16:55 -07:00
// ScrapeTimeout, ScrapeInterval and ScrapeProtocols default to the configured globals.
2023-05-10 16:59:21 -07:00
ScrapeClassicHistograms : false ,
MetricsPath : "/metrics" ,
Scheme : "http" ,
HonorLabels : false ,
HonorTimestamps : true ,
HTTPClientConfig : config . DefaultHTTPClientConfig ,
2023-11-20 04:02:53 -08:00
EnableCompression : true ,
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 {
2023-04-02 03:00:14 -07:00
// With a maximum of 50 shards, assuming an average of 100ms remote write
// time and 2000 samples per batch, we will be able to push 1M samples/s.
MaxShards : 50 ,
2018-12-04 09:32:14 -08:00
MinShards : 1 ,
2023-03-31 01:47:06 -07:00
MaxSamplesPerSend : 2000 ,
2017-07-25 05:47:34 -07:00
2023-04-02 03:00:14 -07:00
// Each shard will have a max of 10,000 samples pending in its channel, plus the pending
// samples that have been enqueued. Theoretically we should only ever have about 12,000 samples
// per shard pending. At 50 shards that's 600k.
Capacity : 10000 ,
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 ) ,
2023-03-31 01:47:06 -07:00
MaxSamplesPerSend : 2000 ,
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 {
2023-02-24 02:47:12 -08:00
GlobalConfig GlobalConfig ` yaml:"global" `
2024-04-01 08:34:35 -07:00
Runtime RuntimeConfig ` yaml:"runtime,omitempty" `
2023-02-24 02:47:12 -08:00
AlertingConfig AlertingConfig ` yaml:"alerting,omitempty" `
RuleFiles [ ] string ` yaml:"rule_files,omitempty" `
ScrapeConfigFiles [ ] string ` yaml:"scrape_config_files,omitempty" `
ScrapeConfigs [ ] * ScrapeConfig ` yaml:"scrape_configs,omitempty" `
StorageConfig StorageConfig ` yaml:"storage,omitempty" `
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
}
2023-02-24 02:47:12 -08:00
for i , file := range c . ScrapeConfigFiles {
c . ScrapeConfigFiles [ i ] = config . JoinDir ( dir , file )
}
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
2023-10-10 03:16:55 -07:00
// GetScrapeConfigs returns the scrape configurations.
2023-02-24 02:47:12 -08:00
func ( c * Config ) GetScrapeConfigs ( ) ( [ ] * ScrapeConfig , error ) {
scfgs := make ( [ ] * ScrapeConfig , len ( c . ScrapeConfigs ) )
jobNames := map [ string ] string { }
for i , scfg := range c . ScrapeConfigs {
// We do these checks for library users that would not call Validate in
// Unmarshal.
2023-05-30 01:22:23 -07:00
if err := scfg . Validate ( c . GlobalConfig ) ; err != nil {
2023-02-24 02:47:12 -08:00
return nil , err
}
if _ , ok := jobNames [ scfg . JobName ] ; ok {
return nil , fmt . Errorf ( "found multiple scrape configs with job name %q" , scfg . JobName )
}
jobNames [ scfg . JobName ] = "main config file"
scfgs [ i ] = scfg
}
for _ , pat := range c . ScrapeConfigFiles {
fs , err := filepath . Glob ( pat )
if err != nil {
// The only error can be a bad pattern.
return nil , fmt . Errorf ( "error retrieving scrape config files for %q: %w" , pat , err )
}
for _ , filename := range fs {
cfg := ScrapeConfigs { }
content , err := os . ReadFile ( filename )
if err != nil {
return nil , fileErr ( filename , err )
}
err = yaml . UnmarshalStrict ( content , & cfg )
if err != nil {
return nil , fileErr ( filename , err )
}
for _ , scfg := range cfg . ScrapeConfigs {
2023-05-30 01:22:23 -07:00
if err := scfg . Validate ( c . GlobalConfig ) ; err != nil {
2023-02-24 02:47:12 -08:00
return nil , fileErr ( filename , err )
}
if f , ok := jobNames [ scfg . JobName ] ; ok {
return nil , fileErr ( filename , fmt . Errorf ( "found multiple scrape configs with job name %q, first found in %s" , scfg . JobName , f ) )
}
jobNames [ scfg . JobName ] = fmt . Sprintf ( "%q" , filePath ( filename ) )
scfg . SetDirectory ( filepath . Dir ( filename ) )
scfgs = append ( scfgs , scfg )
}
}
}
return scfgs , nil
}
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
}
2024-04-01 08:34:35 -07:00
// If a runtime block was open but empty the default runtime config is overwritten.
// We have to restore it here.
if c . Runtime . isZero ( ) {
c . Runtime = DefaultRuntimeConfig
// Use the GOGC env var value if the runtime section is empty.
c . Runtime . GoGC = getGoGCEnv ( )
}
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
}
}
2023-02-24 02:47:12 -08:00
for _ , sf := range c . ScrapeConfigFiles {
if ! patRulePath . MatchString ( sf ) {
return fmt . Errorf ( "invalid scrape config file path %q" , sf )
}
}
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 {
2023-05-30 01:22:23 -07:00
if err := scfg . Validate ( c . GlobalConfig ) ; err != nil {
2023-02-24 02:47:12 -08:00
return err
2016-02-15 02:08:49 -08:00
}
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" `
2023-10-10 03:16:55 -07:00
// The protocols to negotiate during a scrape. It tells clients what
// protocol are accepted by Prometheus and with what weight (most wanted is first).
// Supported values (case sensitive): PrometheusProto, OpenMetricsText0.0.1,
// OpenMetricsText1.0.0, PrometheusText0.0.4.
ScrapeProtocols [ ] ScrapeProtocol ` yaml:"scrape_protocols,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" `
2024-05-30 03:49:50 -07:00
// Offset the rule evaluation timestamp of this particular group by the specified duration into the past to ensure the underlying metrics have been received.
2024-06-05 08:35:52 -07:00
RuleQueryOffset model . Duration ` yaml:"rule_query_offset,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" `
2023-05-30 01:22:23 -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" `
// More than this many samples post metric-relabeling will cause the scrape to
// fail. 0 means no limit.
SampleLimit uint ` yaml:"sample_limit,omitempty" `
// More than this many targets after the target relabeling will cause the
// scrapes to fail. 0 means no limit.
TargetLimit uint ` yaml:"target_limit,omitempty" `
// More than this many labels post metric-relabeling will cause the scrape to
// fail. 0 means no limit.
LabelLimit uint ` yaml:"label_limit,omitempty" `
// More than this label name length post metric-relabeling will cause the
// scrape to fail. 0 means no limit.
LabelNameLengthLimit uint ` yaml:"label_name_length_limit,omitempty" `
// More than this label value length post metric-relabeling will cause the
// scrape to fail. 0 means no limit.
LabelValueLengthLimit uint ` yaml:"label_value_length_limit,omitempty" `
2023-08-14 07:39:25 -07:00
// Keep no more than this many dropped targets per job.
// 0 means no limit.
KeepDroppedTargets uint ` yaml:"keep_dropped_targets,omitempty" `
2013-01-07 14:24:26 -08:00
}
2023-10-10 03:16:55 -07:00
// ScrapeProtocol represents supported protocol for scraping metrics.
type ScrapeProtocol string
// Validate returns error if given scrape protocol is not supported.
func ( s ScrapeProtocol ) Validate ( ) error {
if _ , ok := ScrapeProtocolsHeaders [ s ] ; ! ok {
return fmt . Errorf ( "unknown scrape protocol %v, supported: %v" ,
s , func ( ) ( ret [ ] string ) {
for k := range ScrapeProtocolsHeaders {
ret = append ( ret , string ( k ) )
}
sort . Strings ( ret )
return ret
} ( ) )
}
return nil
}
var (
PrometheusProto ScrapeProtocol = "PrometheusProto"
PrometheusText0_0_4 ScrapeProtocol = "PrometheusText0.0.4"
OpenMetricsText0_0_1 ScrapeProtocol = "OpenMetricsText0.0.1"
OpenMetricsText1_0_0 ScrapeProtocol = "OpenMetricsText1.0.0"
ScrapeProtocolsHeaders = map [ ScrapeProtocol ] string {
PrometheusProto : "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited" ,
PrometheusText0_0_4 : "text/plain;version=0.0.4" ,
OpenMetricsText0_0_1 : "application/openmetrics-text;version=0.0.1" ,
OpenMetricsText1_0_0 : "application/openmetrics-text;version=1.0.0" ,
}
2023-12-11 00:43:42 -08:00
// DefaultScrapeProtocols is the set of scrape protocols that will be proposed
// to scrape target, ordered by priority.
2023-10-10 03:16:55 -07:00
DefaultScrapeProtocols = [ ] ScrapeProtocol {
OpenMetricsText1_0_0 ,
OpenMetricsText0_0_1 ,
PrometheusText0_0_4 ,
}
2023-12-11 00:43:42 -08:00
// DefaultProtoFirstScrapeProtocols is like DefaultScrapeProtocols, but it
// favors protobuf Prometheus exposition format.
// Used by default for certain feature-flags like
// "native-histograms" and "created-timestamp-zero-ingestion".
DefaultProtoFirstScrapeProtocols = [ ] ScrapeProtocol {
2023-10-10 03:16:55 -07:00
PrometheusProto ,
OpenMetricsText1_0_0 ,
OpenMetricsText0_0_1 ,
PrometheusText0_0_4 ,
}
)
// validateAcceptScrapeProtocols return errors if we see problems with accept scrape protocols option.
func validateAcceptScrapeProtocols ( sps [ ] ScrapeProtocol ) error {
if len ( sps ) == 0 {
return errors . New ( "scrape_protocols cannot be empty" )
}
dups := map [ string ] struct { } { }
for _ , sp := range sps {
if _ , ok := dups [ strings . ToLower ( string ( sp ) ) ] ; ok {
return fmt . Errorf ( "duplicated protocol in scrape_protocols, got %v" , sps )
}
if err := sp . Validate ( ) ; err != nil {
return fmt . Errorf ( "scrape_protocols: %w" , err )
}
dups [ strings . ToLower ( string ( sp ) ) ] = struct { } { }
}
return nil
}
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
2022-03-09 14:26:05 -08:00
if err := gc . ExternalLabels . Validate ( func ( l labels . Label ) error {
2019-03-08 08:29:25 -08:00
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
}
2022-03-09 14:26:05 -08:00
return nil
} ) ; err != nil {
return err
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
}
2023-10-10 03:16:55 -07:00
if gc . ScrapeProtocols == nil {
gc . ScrapeProtocols = DefaultGlobalConfig . ScrapeProtocols
}
if err := validateAcceptScrapeProtocols ( gc . ScrapeProtocols ) ; err != nil {
return fmt . Errorf ( "%w for global config" , err )
}
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 {
2022-03-09 14:26:05 -08:00
return c . ExternalLabels . IsEmpty ( ) &&
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 &&
2024-05-30 03:49:50 -07:00
c . RuleQueryOffset == 0 &&
2023-10-10 03:16:55 -07:00
c . QueryLogFile == "" &&
c . ScrapeProtocols == nil
2015-07-17 10:58:34 -07:00
}
2024-04-01 08:34:35 -07:00
// RuntimeConfig configures the values for the process behavior.
type RuntimeConfig struct {
// The Go garbage collection target percentage.
GoGC int ` yaml:"gogc,omitempty" `
}
// isZero returns true iff the global config is the zero value.
func ( c * RuntimeConfig ) isZero ( ) bool {
return c . GoGC == 0
}
2023-02-24 02:47:12 -08:00
type ScrapeConfigs struct {
ScrapeConfigs [ ] * ScrapeConfig ` yaml:"scrape_configs,omitempty" `
}
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" `
2023-10-31 13:58:42 -07:00
// Indicator whether to track the staleness of the scraped timestamps.
TrackTimestampsStaleness bool ` yaml:"track_timestamps_staleness" `
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" `
2023-10-10 03:16:55 -07:00
// The protocols to negotiate during a scrape. It tells clients what
// protocol are accepted by Prometheus and with what preference (most wanted is first).
// Supported values (case sensitive): PrometheusProto, OpenMetricsText0.0.1,
// OpenMetricsText1.0.0, PrometheusText0.0.4.
ScrapeProtocols [ ] ScrapeProtocol ` yaml:"scrape_protocols,omitempty" `
2023-05-10 16:59:21 -07:00
// Whether to scrape a classic histogram that is also exposed as a native histogram.
ScrapeClassicHistograms bool ` yaml:"scrape_classic_histograms,omitempty" `
2016-11-23 03:41:19 -08:00
// 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" `
2023-11-20 04:02:53 -08:00
// Indicator whether to request compressed response from the target.
EnableCompression bool ` yaml:"enable_compression" `
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
2023-05-30 01:22:23 -07:00
// fail. 0 means no limit.
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
2023-05-30 01:22:23 -07:00
// scrapes to fail. 0 means no limit.
2020-07-30 05:20:24 -07:00
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
2023-05-30 01:22:23 -07:00
// fail. 0 means no limit.
2021-05-06 01:56:21 -07:00
LabelLimit uint ` yaml:"label_limit,omitempty" `
// More than this label name length post metric-relabeling will cause the
2023-05-30 01:22:23 -07:00
// scrape to fail. 0 means no limit.
2021-05-06 01:56:21 -07:00
LabelNameLengthLimit uint ` yaml:"label_name_length_limit,omitempty" `
// More than this label value length post metric-relabeling will cause the
2023-05-30 01:22:23 -07:00
// scrape to fail. 0 means no limit.
2021-05-06 01:56:21 -07:00
LabelValueLengthLimit uint ` yaml:"label_value_length_limit,omitempty" `
2024-01-17 07:58:54 -08:00
// If there are more than this many buckets in a native histogram,
// buckets will be merged to stay within the limit.
2023-05-04 11:29:50 -07:00
NativeHistogramBucketLimit uint ` yaml:"native_histogram_bucket_limit,omitempty" `
2024-01-17 07:58:54 -08:00
// If the growth factor of one bucket to the next is smaller than this,
// buckets will be merged to increase the factor sufficiently.
NativeHistogramMinBucketFactor float64 ` yaml:"native_histogram_min_bucket_factor,omitempty" `
2023-08-14 07:39:25 -07:00
// Keep no more than this many dropped targets per job.
// 0 means no limit.
KeepDroppedTargets uint ` yaml:"keep_dropped_targets,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
}
2023-10-10 03:16:55 -07:00
// Validate validates scrape config, but also fills relevant default values from global config if needed.
2023-05-30 01:22:23 -07:00
func ( c * ScrapeConfig ) Validate ( globalConfig GlobalConfig ) error {
2023-02-24 02:47:12 -08:00
if c == nil {
return errors . New ( "empty or null scrape config section" )
}
// First set the correct scrape interval, then check that the timeout
// (inferred or explicit) is not greater than that.
if c . ScrapeInterval == 0 {
2023-05-30 01:22:23 -07:00
c . ScrapeInterval = globalConfig . ScrapeInterval
2023-02-24 02:47:12 -08:00
}
if c . ScrapeTimeout > c . ScrapeInterval {
return fmt . Errorf ( "scrape timeout greater than scrape interval for scrape config with job name %q" , c . JobName )
}
if c . ScrapeTimeout == 0 {
2023-05-30 01:22:23 -07:00
if globalConfig . ScrapeTimeout > c . ScrapeInterval {
2023-02-24 02:47:12 -08:00
c . ScrapeTimeout = c . ScrapeInterval
} else {
2023-05-30 01:22:23 -07:00
c . ScrapeTimeout = globalConfig . ScrapeTimeout
2023-02-24 02:47:12 -08:00
}
}
2023-05-30 01:22:23 -07:00
if c . BodySizeLimit == 0 {
c . BodySizeLimit = globalConfig . BodySizeLimit
}
if c . SampleLimit == 0 {
c . SampleLimit = globalConfig . SampleLimit
}
if c . TargetLimit == 0 {
c . TargetLimit = globalConfig . TargetLimit
}
if c . LabelLimit == 0 {
c . LabelLimit = globalConfig . LabelLimit
}
if c . LabelNameLengthLimit == 0 {
c . LabelNameLengthLimit = globalConfig . LabelNameLengthLimit
}
if c . LabelValueLengthLimit == 0 {
c . LabelValueLengthLimit = globalConfig . LabelValueLengthLimit
}
2023-08-14 07:39:25 -07:00
if c . KeepDroppedTargets == 0 {
c . KeepDroppedTargets = globalConfig . KeepDroppedTargets
}
2023-05-30 01:22:23 -07:00
2023-10-10 03:16:55 -07:00
if c . ScrapeProtocols == nil {
c . ScrapeProtocols = globalConfig . ScrapeProtocols
}
if err := validateAcceptScrapeProtocols ( c . ScrapeProtocols ) ; err != nil {
return fmt . Errorf ( "%w for scrape config with job name %q" , err , c . JobName )
}
2023-02-24 02:47:12 -08:00
return nil
}
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" `
2023-08-31 18:43:48 -07:00
SigV4Config * sigv4 . SigV4Config ` yaml:"sigv4,omitempty" `
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" `
2023-07-11 14:44:23 -07:00
// Relabel alerts before sending to the specific alertmanager.
AlertRelabelConfigs [ ] * relabel . Config ` yaml:"alert_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
}
2023-08-31 18:43:48 -07:00
httpClientConfigAuthEnabled := c . HTTPClientConfig . BasicAuth != nil ||
c . HTTPClientConfig . Authorization != nil || c . HTTPClientConfig . OAuth2 != nil
if httpClientConfigAuthEnabled && c . SigV4Config != nil {
return fmt . Errorf ( "at most one of basic_auth, authorization, oauth2, & sigv4 must be configured" )
}
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
}
}
2023-07-11 14:44:23 -07:00
for _ , rlcfg := range c . AlertRelabelConfigs {
if rlcfg == nil {
return errors . New ( "empty or null Alertmanager alert relabeling rule" )
}
}
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 {
2022-07-14 06:13:12 -07:00
URL * config . URL ` yaml:"url" `
RemoteTimeout model . Duration ` yaml:"remote_timeout,omitempty" `
Headers map [ string ] string ` yaml:"headers,omitempty" `
WriteRelabelConfigs [ ] * relabel . Config ` yaml:"write_relabel_configs,omitempty" `
Name string ` yaml:"name,omitempty" `
SendExemplars bool ` yaml:"send_exemplars,omitempty" `
SendNativeHistograms bool ` yaml:"send_native_histograms,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" `
2023-06-01 14:20:10 -07:00
AzureADConfig * azuread . AzureADConfig ` yaml:"azuread,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
2023-06-01 14:20:10 -07:00
if httpClientConfigAuthEnabled && ( c . SigV4Config != nil || c . AzureADConfig != nil ) {
return fmt . Errorf ( "at most one of basic_auth, authorization, oauth2, sigv4, & azuread must be configured" )
}
if c . SigV4Config != nil && c . AzureADConfig != nil {
return fmt . Errorf ( "at most one of basic_auth, authorization, oauth2, sigv4, & azuread 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" {
2023-06-01 14:20:10 -07:00
return errors . New ( "authorization header must be changed via the basic_auth, authorization, oauth2, sigv4, or azuread 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" `
2024-01-05 10:40:30 -08:00
// Samples older than the limit will be dropped.
SampleAgeLimit model . Duration ` yaml:"sample_age_limit,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
}
2023-02-24 02:47:12 -08:00
func filePath ( filename string ) string {
absPath , err := filepath . Abs ( filename )
if err != nil {
return filename
}
return absPath
}
func fileErr ( filename string , err error ) error {
return fmt . Errorf ( "%q: %w" , filePath ( filename ) , err )
}
2024-04-01 08:34:35 -07:00
func getGoGCEnv ( ) int {
goGCEnv := os . Getenv ( "GOGC" )
// If the GOGC env var is set, use the same logic as upstream Go.
if goGCEnv != "" {
// Special case for GOGC=off.
if strings . ToLower ( goGCEnv ) == "off" {
return - 1
}
i , err := strconv . Atoi ( goGCEnv )
if err == nil {
return i
}
}
return DefaultRuntimeConfig . GoGC
}