Switch config to YAML format.

This commit is contained in:
Fabian Reinartz 2015-05-07 10:55:03 +02:00
parent 66ecc420ef
commit 5fbde88919
32 changed files with 712 additions and 1319 deletions

View file

@ -14,6 +14,8 @@
package model
import (
"fmt"
"regexp"
"strings"
)
@ -58,10 +60,25 @@ const (
QuantileLabel = "quantile"
)
var labelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$")
// A LabelName is a key for a LabelSet or Metric. It has a value associated
// therewith.
type LabelName string
// UnmarshalYAML implements the yaml.Unmarshaller interface.
func (ln *LabelName) UnmarshalYAML(unmarshal func(interface{}) error) error {
var s string
if err := unmarshal(&s); err != nil {
return err
}
if !labelNameRE.MatchString(s) {
return fmt.Errorf("%q is not a valid label name", s)
}
*ln = LabelName(s)
return nil
}
// LabelNames is a sortable LabelName slice. In implements sort.Interface.
type LabelNames []LabelName

View file

@ -26,7 +26,7 @@ advice: $(GOCC)
binary: build
build: config tools web $(GOPATH)
build: tools web $(GOPATH)
$(GO) build -o prometheus $(BUILDFLAGS) .
docker: build
@ -49,7 +49,7 @@ tag:
$(BUILD_PATH)/cache/$(GOPKG):
$(CURL) -o $@ -L $(GOURL)/$(GOPKG)
benchmark: config dependencies tools web
benchmark: dependencies tools web
$(GO) test $(GO_TEST_FLAGS) -test.run='NONE' -test.bench='.*' -test.benchmem ./... | tee benchmark.txt
clean:
@ -62,9 +62,6 @@ clean:
-find . -type f -name '*#' -exec rm '{}' ';'
-find . -type f -name '.#*' -exec rm '{}' ';'
config:
$(MAKE) -C config
$(SELFLINK): $(GOPATH)
ln -s $(MAKEFILE_DIR) $@
@ -91,7 +88,7 @@ run: binary
search_index:
godoc -index -write_index -index_files='search_index'
test: config dependencies tools web
test: dependencies tools web
$(GO) test $(GO_TEST_FLAGS) ./...
tools: dependencies
@ -103,4 +100,4 @@ web: dependencies
rules: dependencies
$(MAKE) -C rules
.PHONY: advice binary build clean config dependencies documentation format race_condition_binary race_condition_run release run search_index tag tarball test tools
.PHONY: advice binary build clean dependencies documentation format race_condition_binary race_condition_run release run search_index tag tarball test tools

View file

@ -1,22 +0,0 @@
# Copyright 2013 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.
all: generated/config.pb.go
SUFFIXES:
include ../Makefile.INCLUDE
generated/config.pb.go: config.proto
go get github.com/golang/protobuf/protoc-gen-go
$(PROTOC) --proto_path=$(PREFIX)/include:. --go_out=generated/ config.proto

View file

@ -1,269 +1,359 @@
// Copyright 2013 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.
package config
import (
"errors"
"fmt"
"io/ioutil"
"regexp"
"strings"
"time"
"github.com/golang/protobuf/proto"
"gopkg.in/yaml.v2"
clientmodel "github.com/prometheus/client_golang/model"
"github.com/prometheus/prometheus/utility"
pb "github.com/prometheus/prometheus/config/generated"
)
var (
jobNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_-]*$")
labelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$")
)
var jobNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_-]*$")
// Config encapsulates the configuration of a Prometheus instance. It wraps the
// raw configuration protocol buffer to be able to add custom methods to it.
type Config struct {
// The protobuf containing the actual configuration values.
pb.PrometheusConfig
// Load parses the YAML input s into a Config.
func Load(s string) (*Config, error) {
cfg := &Config{
original: s,
}
// String returns an ASCII serialization of the loaded configuration protobuf.
func (c *Config) String() string {
return proto.MarshalTextString(&c.PrometheusConfig)
}
// validateLabels validates whether label names have the correct format.
func validateLabels(labels *pb.LabelPairs) error {
if labels == nil {
return nil
}
for _, label := range labels.Label {
if !labelNameRE.MatchString(label.GetName()) {
return fmt.Errorf("invalid label name '%s'", label.GetName())
}
}
return nil
}
// validateHosts validates whether a target group contains valid hosts.
func validateHosts(hosts []string) error {
if hosts == nil {
return nil
}
for _, host := range hosts {
// Make sure that this does not contain any paths or schemes.
// This ensures that old configurations error.
if strings.Contains(host, "/") {
return fmt.Errorf("invalid host '%s', no schemes or paths allowed", host)
}
}
return nil
}
// Validate checks an entire parsed Config for the validity of its fields.
func (c *Config) Validate() error {
// Check the global configuration section for validity.
global := c.Global
if _, err := utility.StringToDuration(global.GetScrapeInterval()); err != nil {
return fmt.Errorf("invalid global scrape interval: %s", err)
}
if _, err := utility.StringToDuration(global.GetEvaluationInterval()); err != nil {
return fmt.Errorf("invalid rule evaluation interval: %s", err)
}
if err := validateLabels(global.Labels); err != nil {
return fmt.Errorf("invalid global labels: %s", err)
}
// Check each scrape configuration for validity.
jobNames := map[string]struct{}{}
for _, sc := range c.ScrapeConfigs() {
name := sc.GetJobName()
if _, ok := jobNames[name]; ok {
return fmt.Errorf("found multiple scrape configs configured with the same job name: %q", name)
}
jobNames[name] = struct{}{}
if err := sc.Validate(); err != nil {
return fmt.Errorf("error in scrape config %q: %s", name, err)
}
}
return nil
}
// GlobalLabels returns the global labels as a LabelSet.
func (c *Config) GlobalLabels() clientmodel.LabelSet {
labels := clientmodel.LabelSet{}
if c.Global != nil && c.Global.Labels != nil {
for _, label := range c.Global.Labels.Label {
labels[clientmodel.LabelName(label.GetName())] = clientmodel.LabelValue(label.GetValue())
}
}
return labels
}
// ScrapeConfigs returns all scrape configurations.
func (c *Config) ScrapeConfigs() (cfgs []*ScrapeConfig) {
for _, sc := range c.GetScrapeConfig() {
cfgs = append(cfgs, &ScrapeConfig{*sc})
}
return
}
// stringToDuration converts a string to a duration and dies on invalid format.
func stringToDuration(intervalStr string) time.Duration {
duration, err := utility.StringToDuration(intervalStr)
err := yaml.Unmarshal([]byte(s), cfg)
if err != nil {
panic(err)
return nil, err
}
return duration
return cfg, nil
}
// ScrapeInterval gets the default scrape interval for a Config.
func (c *Config) ScrapeInterval() time.Duration {
return stringToDuration(c.Global.GetScrapeInterval())
// LoadFromFile parses the given YAML file into a Config.
func LoadFromFile(filename string) (*Config, error) {
content, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
return Load(string(content))
}
// EvaluationInterval gets the default evaluation interval for a Config.
func (c *Config) EvaluationInterval() time.Duration {
return stringToDuration(c.Global.GetEvaluationInterval())
// The defaults applied before parsing the respective config sections.
var (
// The default top-level configuration.
DefaultConfig = DefaultedConfig{
GlobalConfig: &GlobalConfig{DefaultGlobalConfig},
}
// ScrapeConfig encapsulates a protobuf scrape configuration.
// The default global configuration.
DefaultGlobalConfig = DefaultedGlobalConfig{
ScrapeInterval: Duration(10 * time.Second),
ScrapeTimeout: Duration(10 * time.Second),
EvaluationInterval: Duration(1 * time.Minute),
}
// Te default scrape configuration.
DefaultScrapeConfig = DefaultedScrapeConfig{
// ScrapeTimeout and ScrapeInterval default to the
// configured globals.
MetricsPath: "/metrics",
Scheme: "http",
}
// The default Relabel configuration.
DefaultRelabelConfig = DefaultedRelabelConfig{
Action: RelabelReplace,
Separator: ";",
}
// The default DNS SD configuration.
DefaultDNSConfig = DefaultedDNSConfig{
RefreshInterval: Duration(30 * time.Second),
}
)
// Config is the top-level configuration for Prometheus's config files.
type Config struct {
// DefaultedConfig contains the actual fields of Config.
DefaultedConfig `yaml:",inline"`
// original is the input from which the config was parsed.
original string
}
func (c *Config) String() string {
if c.original != "" {
return c.original
}
b, err := yaml.Marshal(c)
if err != nil {
return fmt.Sprintf("<error creating config string: %s>", err)
}
return string(b)
}
// UnmarshalYAML implements the yaml.Unmarshaller interface.
func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
c.DefaultedConfig = DefaultConfig
if err := unmarshal(&c.DefaultedConfig); err != nil {
return err
}
// Do global overrides and validate unique names.
jobNames := map[string]struct{}{}
for _, scfg := range c.ScrapeConfigs {
if scfg.ScrapeInterval == 0 {
scfg.ScrapeInterval = c.GlobalConfig.ScrapeInterval
}
if scfg.ScrapeTimeout == 0 {
scfg.ScrapeTimeout = c.GlobalConfig.ScrapeTimeout
}
if _, ok := jobNames[scfg.JobName]; ok {
return fmt.Errorf("found multiple scrape configs with job name %q", scfg.JobName)
}
jobNames[scfg.JobName] = struct{}{}
}
return nil
}
// DefaultedConfig is a proxy type for Config.
type DefaultedConfig struct {
GlobalConfig *GlobalConfig `yaml:"global_config"`
RuleFiles []string `yaml:"rule_files,omitempty"`
ScrapeConfigs []*ScrapeConfig `yaml:"scrape_configs,omitempty"`
}
// GlobalConfig configures values that used across other configuration
// objects.
type GlobalConfig struct {
// DefaultedGlobalConfig contains the actual fields for GlobalConfig.
DefaultedGlobalConfig `yaml:",inline"`
}
// UnmarshalYAML implements the yaml.Unmarshaller interface.
func (c *GlobalConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
c.DefaultedGlobalConfig = DefaultGlobalConfig
if err := unmarshal(&c.DefaultedGlobalConfig); err != nil {
return err
}
return nil
}
// DefaultedGlobalConfig is a proxy type for GlobalConfig.
type DefaultedGlobalConfig struct {
// How frequently to scrape targets by default.
ScrapeInterval Duration `yaml:"scrape_interval"`
// The default timeout when scraping targets.
ScrapeTimeout Duration `yaml:"scrape_timeout"`
// How frequently to evaluate rules by default.
EvaluationInterval Duration `yaml:"evaluation_interval"`
// The labels to add to any timeseries that this Prometheus instance scrapes.
Labels clientmodel.LabelSet `yaml:"labels,omitempty"`
}
// ScrapeConfig configures a scraping unit for Prometheus.
type ScrapeConfig struct {
pb.ScrapeConfig
// DefaultedScrapeConfig contains the actual fields for ScrapeConfig.
DefaultedScrapeConfig `yaml:",inline"`
}
// ScrapeInterval gets the scrape interval for the scrape config.
func (c *ScrapeConfig) ScrapeInterval() time.Duration {
return stringToDuration(c.GetScrapeInterval())
}
// ScrapeTimeout gets the scrape timeout for the scrape config.
func (c *ScrapeConfig) ScrapeTimeout() time.Duration {
return stringToDuration(c.GetScrapeTimeout())
}
// Labels returns a label set for the targets that is implied by the scrape config.
func (c *ScrapeConfig) Labels() clientmodel.LabelSet {
return clientmodel.LabelSet{
clientmodel.MetricsPathLabel: clientmodel.LabelValue(c.GetMetricsPath()),
clientmodel.JobLabel: clientmodel.LabelValue(c.GetJobName()),
}
}
// Validate checks the ScrapeConfig for the validity of its fields
func (c *ScrapeConfig) Validate() error {
name := c.GetJobName()
if !jobNameRE.MatchString(name) {
return fmt.Errorf("invalid job name %q", name)
}
if _, err := utility.StringToDuration(c.GetScrapeInterval()); err != nil {
return fmt.Errorf("invalid scrape interval: %s", err)
}
if _, err := utility.StringToDuration(c.GetScrapeTimeout()); err != nil {
return fmt.Errorf("invalid scrape timeout: %s", err)
}
for _, tgroup := range c.GetTargetGroup() {
if err := validateLabels(tgroup.Labels); err != nil {
return fmt.Errorf("invalid labels: %s", err)
}
if err := validateHosts(tgroup.Target); err != nil {
return fmt.Errorf("invalid targets: %s", err)
}
}
for _, dnscfg := range c.DNSConfigs() {
if err := dnscfg.Validate(); err != nil {
return fmt.Errorf("invalid DNS config: %s", err)
}
}
for _, rlcfg := range c.RelabelConfigs() {
if err := rlcfg.Validate(); err != nil {
return fmt.Errorf("invalid relabelling config: %s", err)
// UnmarshalYAML implements the yaml.Unmarshaller interface.
func (c *ScrapeConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
c.DefaultedScrapeConfig = DefaultScrapeConfig
err := unmarshal(&c.DefaultedScrapeConfig)
if err != nil {
return err
}
if !jobNameRE.MatchString(c.JobName) {
return fmt.Errorf("%q is not a valid job name", c.JobName)
}
return nil
}
// DNSConfigs returns the list of DNS service discovery configurations
// for the scrape config.
func (c *ScrapeConfig) DNSConfigs() []*DNSConfig {
var dnscfgs []*DNSConfig
for _, dc := range c.GetDnsConfig() {
dnscfgs = append(dnscfgs, &DNSConfig{*dc})
}
return dnscfgs
// DefaultedScrapeConfig is a proxy type for ScrapeConfig.
type DefaultedScrapeConfig struct {
// The job name to which the job label is set by default.
JobName string `yaml:"job_name"`
// How frequently to scrape the targets of this scrape config.
ScrapeInterval Duration `yaml:"scrape_interval"`
// The timeout for scraping targets of this config.
ScrapeTimeout Duration `yaml:"scrape_timeout"`
// The HTTP resource path on which to fetch metrics from targets.
MetricsPath string `yaml:"metrics_path"`
// The URL scheme with which to fetch metrics from targets.
Scheme string `yaml:"scheme"`
// List of labeled target groups for this job.
TargetGroups []*TargetGroup `yaml:"target_groups,omitempty"`
// List of DNS service discovery configurations.
DNSConfigs []*DNSConfig `yaml:"dns_configs,omitempty"`
// List of relabel configurations.
RelabelConfigs []*RelabelConfig `yaml:"relabel_configs,omitempty"`
}
// RelabelConfigs returns the relabel configs of the scrape config.
func (c *ScrapeConfig) RelabelConfigs() []*RelabelConfig {
var rlcfgs []*RelabelConfig
for _, rc := range c.GetRelabelConfig() {
rlcfgs = append(rlcfgs, &RelabelConfig{*rc})
}
return rlcfgs
}
// DNSConfig encapsulates the protobuf configuration object for DNS based
// service discovery.
type DNSConfig struct {
pb.DNSConfig
}
// Validate checks the DNSConfig for the validity of its fields.
func (c *DNSConfig) Validate() error {
if _, err := utility.StringToDuration(c.GetRefreshInterval()); err != nil {
return fmt.Errorf("invalid refresh interval: %s", err)
}
return nil
}
// RefreshInterval gets the the refresh interval for DNS service discovery.
func (c *DNSConfig) RefreshInterval() time.Duration {
return stringToDuration(c.GetRefreshInterval())
}
// RelabelConfig encapsulates the protobuf configuration object for relabeling.
type RelabelConfig struct {
pb.RelabelConfig
}
// Validate checks the RelabelConfig for the validity of its fields.
func (c *RelabelConfig) Validate() error {
if len(c.GetSourceLabel()) == 0 {
return errors.New("at least one source label is required")
}
return nil
}
// TargetGroup is derived from a protobuf TargetGroup and attaches a source to it
// that identifies the origin of the group.
// A labeled group of targets to scrape for a job.
type TargetGroup struct {
// Source is an identifier that describes a group of targets.
Source string
// Labels is a set of labels that is common across all targets in the group.
Labels clientmodel.LabelSet
// Targets is a list of targets identified by a label set. Each target is
// uniquely identifiable in the group by its address label.
Targets []clientmodel.LabelSet
Targets []clientmodel.LabelSet `yaml:"targets,omitempty" json:"targets,omitempty"`
// Labels is a set of labels that is common across all targets in the group.
Labels clientmodel.LabelSet `yaml:"labels,omitempty" json:"labels,omitempty"`
// Source is an identifier that describes a group of targets.
Source string `yaml:"-", json:"-"`
}
func (tg *TargetGroup) String() string {
return tg.Source
}
// UnmarshalYAML implements the yaml.Unmarshaller interface.
func (tg *TargetGroup) UnmarshalYAML(unmarshal func(interface{}) error) error {
g := struct {
Targets []string `yaml:"targets"`
Labels clientmodel.LabelSet `yaml:"labels"`
}{}
if err := unmarshal(&g); err != nil {
return err
}
tg.Targets = make([]clientmodel.LabelSet, 0, len(g.Targets))
for _, t := range g.Targets {
if strings.Contains(t, "/") {
return fmt.Errorf("%q is not a valid hostname", t)
}
tg.Targets = append(tg.Targets, clientmodel.LabelSet{
clientmodel.AddressLabel: clientmodel.LabelValue(t),
})
}
tg.Labels = g.Labels
return nil
}
// DNSConfig is the configuration for DNS based service discovery.
type DNSConfig struct {
// DefaultedDNSConfig contains the actual fields for DNSConfig.
DefaultedDNSConfig `yaml:",inline"`
}
// UnmarshalYAML implements the yaml.Unmarshaller interface.
func (c *DNSConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
c.DefaultedDNSConfig = DefaultDNSConfig
err := unmarshal(&c.DefaultedDNSConfig)
if err != nil {
return err
}
if len(c.Names) == 0 {
return fmt.Errorf("DNS config must contain at least one SRV server name")
}
return nil
}
// DefaultedDNSConfig is a proxy type for DNSConfig.
type DefaultedDNSConfig struct {
Names []string `yaml:"names"`
RefreshInterval Duration `yaml:"refresh_interval"`
}
// RelabelAction is the action to be performed on relabeling.
type RelabelAction string
const (
// Performs a regex replacement.
RelabelReplace RelabelAction = "replace"
// Drops targets for which the input does not match the regex.
RelabelKeep = "keep"
// Drops targets for which the input does match the regex.
RelabelDrop = "drop"
)
// UnmarshalYAML implements the yaml.Unmarshaller interface.
func (a *RelabelAction) UnmarshalYAML(unmarshal func(interface{}) error) error {
var s string
if err := unmarshal(&s); err != nil {
return err
}
switch act := RelabelAction(strings.ToLower(s)); act {
case RelabelReplace, RelabelKeep, RelabelDrop:
*a = act
return nil
}
return fmt.Errorf("unknown relabel action %q", s)
}
// RelabelConfig is the configuration for relabeling of target label sets.
type RelabelConfig struct {
// DefaultedRelabelConfig contains the actual fields for RelabelConfig.
DefaultedRelabelConfig `yaml:",inline"`
}
// UnmarshalYAML implements the yaml.Unmarshaller interface.
func (c *RelabelConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
c.DefaultedRelabelConfig = DefaultRelabelConfig
return unmarshal(&c.DefaultedRelabelConfig)
}
// DefaultedRelabelConfig is a proxy type for RelabelConfig.
type DefaultedRelabelConfig struct {
// A list of labels from which values are taken and concatenated
// with the configured separator in order.
SourceLabels clientmodel.LabelNames `yaml:"source_labels,flow"`
// Separator is the string between concatenated values from the source labels.
Separator string `yaml:"separator"`
// Regex against which the concatenation is matched.
Regex *Regexp `yaml:"regex"`
// The label to which the resulting string is written in a replacement.
TargetLabel clientmodel.LabelName `yaml:"target_label,omitempty"`
// Replacement is the regex replacement pattern to be used.
Replacement string `yaml:"replacement,omitempty"`
// Action is the action to be performed for the relabeling.
Action RelabelAction `yaml:"action"`
}
// Regexp encapsulates a regexp.Regexp and makes it YAML marshallable.
type Regexp struct {
regexp.Regexp
}
// UnmarshalYAML implements the yaml.Unmarshaller interface.
func (re *Regexp) UnmarshalYAML(unmarshal func(interface{}) error) error {
var s string
if err := unmarshal(&s); err != nil {
return err
}
regex, err := regexp.Compile(s)
if err != nil {
return err
}
re.Regexp = *regex
return nil
}
// MarshalYAML implements the yaml.Marshaller interface.
func (re *Regexp) MarshalYAML() (interface{}, error) {
return re.String(), nil
}
// Duration encapsulates a time.Duration and makes it YAML marshallable.
//
// TODO(fabxc): Since we have custom types for most things, including timestamps,
// we might want to move this into our model as well, eventually.
type Duration time.Duration
// UnmarshalYAML implements the yaml.Unmarshaller interface.
func (d *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error {
var s string
if err := unmarshal(&s); err != nil {
return err
}
dur, err := utility.StringToDuration(s)
if err != nil {
return err
}
*d = Duration(dur)
return nil
}
// MarshalYAML implements the yaml.Marshaller interface.
func (d Duration) MarshalYAML() (interface{}, error) {
return utility.DurationToString(time.Duration(d)), nil
}

View file

@ -1,117 +0,0 @@
// Copyright 2013 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.
package io.prometheus;
// A label/value pair suitable for attaching to timeseries.
message LabelPair {
// The name of the label. Must adhere to the regex "[a-zA-Z_][a-zA-Z0-9_]*".
optional string name = 1;
// The value of the label. May contain any characters.
optional string value = 2;
}
// A set of label/value pairs.
message LabelPairs {
repeated LabelPair label = 1;
}
// The global Prometheus configuration section.
message GlobalConfig {
// How frequently to scrape targets by default. Must be a valid Prometheus
// duration string in the form "[0-9]+[smhdwy]".
optional string scrape_interval = 1 [default = "1m"];
// How frequently to evaluate rules by default. Must be a valid Prometheus
// duration string in the form "[0-9]+[smhdwy]".
optional string evaluation_interval = 2 [default = "1m"];
// The labels to add to any timeseries that this Prometheus instance scrapes.
optional LabelPairs labels = 3;
// The list of file names of rule files to load.
repeated string rule_file = 4;
}
// A labeled group of targets to scrape for a job.
message TargetGroup {
// The list of endpoints to scrape via HTTP.
repeated string target = 1;
// The labels to add to any timeseries scraped for this target group.
optional LabelPairs labels = 2;
}
// The configuration for DNS based service discovery.
message DNSConfig {
// The list of DNS-SD service names pointing to SRV records
// containing endpoint information.
repeated string name = 1;
// Discovery refresh period when using DNS-SD to discover targets. Must be a
// valid Prometheus duration string in the form "[0-9]+[smhdwy]".
optional string refresh_interval = 2 [default = "30s"];
}
// The configuration for relabeling of target label sets.
message RelabelConfig {
// A list of labels from which values are taken and concatenated
// with the configured separator in order.
repeated string source_label = 1;
// Regex against which the concatenation is matched.
required string regex = 2;
// The label to which the resulting string is written in a replacement.
optional string target_label = 3;
// Replacement is the regex replacement pattern to be used.
optional string replacement = 4;
// Separator is the string between concatenated values from the source labels.
optional string separator = 5 [default = ";"];
// Action is the action to be performed for the relabeling.
enum Action {
REPLACE = 0; // Performs a regex replacement.
KEEP = 1; // Drops targets for which the input does not match the regex.
DROP = 2; // Drops targets for which the input does match the regex.
}
optional Action action = 6 [default = REPLACE];
}
// The configuration for a Prometheus job to scrape.
//
// The next field no. is 11.
message ScrapeConfig {
// The job name. Must adhere to the regex "[a-zA-Z_][a-zA-Z0-9_-]*".
required string job_name = 1;
// How frequently to scrape targets from this job. Overrides the global
// default. Must be a valid Prometheus duration string in the form
// "[0-9]+[smhdwy]".
optional string scrape_interval = 2;
// Per-target timeout when scraping this job. Must be a valid Prometheus
// duration string in the form "[0-9]+[smhdwy]".
optional string scrape_timeout = 7 [default = "10s"];
// List of DNS service discovery configurations.
repeated DNSConfig dns_config = 9;
// List of labeled target groups for this job.
repeated TargetGroup target_group = 5;
// List of relabel configurations.
repeated RelabelConfig relabel_config = 10;
// The HTTP resource path on which to fetch metrics from targets.
optional string metrics_path = 6 [default = "/metrics"];
// The URL scheme with which to fetch metrics from targets.
optional string scheme = 8 [default = "http"];
}
// The top-level Prometheus configuration.
message PrometheusConfig {
// Global Prometheus configuration options. If omitted, an empty global
// configuration with default values (see GlobalConfig definition) will be
// created.
optional GlobalConfig global = 1;
// The list of scrape configs.
repeated ScrapeConfig scrape_config = 3;
}

View file

@ -1,80 +1,152 @@
// Copyright 2013 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.
package config
import (
"path"
"reflect"
"regexp"
"strings"
"testing"
"time"
"gopkg.in/yaml.v2"
clientmodel "github.com/prometheus/client_golang/model"
)
var fixturesPath = "fixtures"
var expectedConf = &Config{DefaultedConfig{
GlobalConfig: &GlobalConfig{DefaultedGlobalConfig{
ScrapeInterval: Duration(15 * time.Second),
ScrapeTimeout: DefaultGlobalConfig.ScrapeTimeout,
EvaluationInterval: Duration(30 * time.Second),
var configTests = []struct {
inputFile string
shouldFail bool
errContains string
Labels: clientmodel.LabelSet{
"monitor": "codelab",
"foo": "bar",
},
}},
RuleFiles: []string{
"first.rules",
"second.rules",
},
ScrapeConfigs: []*ScrapeConfig{
{DefaultedScrapeConfig{
JobName: "prometheus",
ScrapeInterval: Duration(15 * time.Second),
ScrapeTimeout: DefaultGlobalConfig.ScrapeTimeout,
MetricsPath: DefaultScrapeConfig.MetricsPath,
Scheme: DefaultScrapeConfig.Scheme,
TargetGroups: []*TargetGroup{
{
Targets: []clientmodel.LabelSet{
{clientmodel.AddressLabel: "localhost:9090"},
{clientmodel.AddressLabel: "localhost:9191"},
},
Labels: clientmodel.LabelSet{
"my": "label",
"your": "label",
},
},
},
RelabelConfigs: []*RelabelConfig{
{DefaultedRelabelConfig{
SourceLabels: clientmodel.LabelNames{"job", "__meta_dns_srv_name"},
TargetLabel: "job",
Separator: ";",
Regex: &Regexp{*regexp.MustCompile("(.*)some-[regex]$")},
Replacement: "foo-${1}",
Action: RelabelReplace,
}},
},
}},
{DefaultedScrapeConfig{
JobName: "service-x",
ScrapeInterval: Duration(50 * time.Second),
ScrapeTimeout: Duration(5 * time.Second),
MetricsPath: "/my_path",
Scheme: "http",
DNSConfigs: []*DNSConfig{
{DefaultedDNSConfig{
Names: []string{
"first.dns.address.domain.com",
"second.dns.address.domain.com",
},
RefreshInterval: Duration(15 * time.Second),
}},
{DefaultedDNSConfig{
Names: []string{
"first.dns.address.domain.com",
},
RefreshInterval: Duration(30 * time.Second),
}},
},
RelabelConfigs: []*RelabelConfig{
{DefaultedRelabelConfig{
SourceLabels: clientmodel.LabelNames{"job"},
Regex: &Regexp{*regexp.MustCompile("(.*)some-[regex]$")},
Separator: ";",
Action: RelabelDrop,
}},
},
}},
},
}, ""}
func TestLoadConfig(t *testing.T) {
c, err := LoadFromFile("testdata/conf.good.yml")
if err != nil {
t.Errorf("Error parsing %s: %s", "testdata/conf.good.yml", err)
}
bgot, err := yaml.Marshal(c)
if err != nil {
t.Errorf("%s", err)
}
bexp, err := yaml.Marshal(expectedConf)
if err != nil {
t.Errorf("%s", err)
}
expectedConf.original = c.original
if !reflect.DeepEqual(c, expectedConf) {
t.Errorf("%s: unexpected config result: \n\n%s\n expected\n\n%s", "testdata/conf.good.yml", bgot, bexp)
}
}
var expectedErrors = []struct {
filename string
errMsg string
}{
{
inputFile: "minimal.conf.input",
filename: "jobname.bad.yml",
errMsg: `"prom^etheus" is not a valid job name`,
}, {
inputFile: "sample.conf.input",
filename: "jobname_dup.bad.yml",
errMsg: `found multiple scrape configs with job name "prometheus"`,
}, {
inputFile: "empty.conf.input",
filename: "labelname.bad.yml",
errMsg: `"not$allowed" is not a valid label name`,
}, {
inputFile: "sd_targets.conf.input",
}, {
inputFile: "full.conf.input",
}, {
inputFile: "invalid_proto_format.conf.input",
shouldFail: true,
errContains: "unknown field name",
},
{
inputFile: "invalid_scrape_interval.conf.input",
shouldFail: true,
errContains: "invalid global scrape interval",
},
{
inputFile: "invalid_job_name.conf.input",
shouldFail: true,
errContains: "invalid job name",
},
{
inputFile: "invalid_label_name.conf.input",
shouldFail: true,
errContains: "invalid label name",
},
{
inputFile: "repeated_job_name.conf.input",
shouldFail: true,
errContains: "found multiple scrape configs configured with the same job name: \"testjob1\"",
filename: "regex.bad.yml",
errMsg: "error parsing regexp",
},
}
func TestConfigs(t *testing.T) {
for i, configTest := range configTests {
_, err := LoadFromFile(path.Join(fixturesPath, configTest.inputFile))
if err != nil {
if !configTest.shouldFail {
t.Fatalf("%d. Error parsing config %v: %v", i, configTest.inputFile, err)
} else {
if !strings.Contains(err.Error(), configTest.errContains) {
t.Fatalf("%d. Expected error containing '%v', got: %v", i, configTest.errContains, err)
}
}
func TestBadConfigs(t *testing.T) {
for _, ee := range expectedErrors {
_, err := LoadFromFile("testdata/" + ee.filename)
if err == nil {
t.Errorf("Expected error parsing %s but got none", ee.filename)
}
if !strings.Contains(err.Error(), ee.errMsg) {
t.Errorf("Expected error for %s to contain %q but got: %s", ee.filename, ee.errMsg, err)
}
}
}

View file

@ -1,89 +0,0 @@
global <
scrape_interval: "30s"
evaluation_interval: "30s"
labels: <
label: <
name: "monitor"
value: "test"
>
label: <
name: "more"
value: "test"
>
>
rule_file: "prometheus.rules"
rule_file: "prometheus.more.rules"
>
scrape_config: <
job_name: "prometheus"
scrape_interval: "15s"
metrics_path: "/metrics"
scheme: "http"
target_group: <
target: "localhost:9090"
>
>
scrape_config: <
job_name: "myjob"
scrape_interval: "15s"
metrics_path: "/metrics"
scheme: "http"
dns_config: <
name: "first.srv.name"
name: "second.srv.name"
refresh_interval: "1h"
>
dns_config: <
name: "first2.srv.name"
name: "second2.srv.name"
refresh_interval: "1m"
>
relabel_config: <
source_label: "l1"
source_label: "l2"
regex: "^foobar.*$"
target_label: "l3"
replacement: "static"
>
relabel_config: <
source_label: "l4"
regex: "^foobar.*$"
action: DROP
>
relabel_config: <
source_label: "l4"
regex: "^foobar.*$"
action: KEEP
>
target_group: <
target: "localhost:9090"
target: "localhost:9091"
labels: <
label: <
name: "tg1"
value: "tg1"
>
>
>
target_group: <
target: "my.domain:9090"
target: "my.domain:9091"
labels: <
label: <
name: "tg2"
value: "tg2"
>
label: <
name: "tg2_1"
value: "tg2_1"
>
>
>
>

View file

@ -1,3 +0,0 @@
scrape_config: <
job_name: "1testjob"
>

View file

@ -1,10 +0,0 @@
global <
scrape_interval: "30s"
evaluation_interval: "30s"
labels: <
label: <
name: "monitor-test"
value: "test"
>
>
>

View file

@ -1,11 +0,0 @@
global <
scrape_interval: "30s"
evaluation_interval: "30s"
unknown_field: "foo"
labels: <
label: <
name: "monitor"
value: "test"
>
>
>

View file

@ -1,10 +0,0 @@
global <
scrape_interval: "30"
evaluation_interval: "30s"
labels: <
label: <
name: "monitor"
value: "test"
>
>
>

View file

@ -1,22 +0,0 @@
global <
scrape_interval: "30s"
evaluation_interval: "30s"
labels: <
label: <
name: "monitor"
value: "test"
>
>
rule_file: "prometheus.rules"
>
scrape_config: <
job_name: "prometheus"
scrape_interval: "15s"
metrics_path: "/metrics"
scheme: "http"
target_group: <
target: "localhost:9090"
>
>

View file

@ -1,11 +0,0 @@
scrape_config: <
job_name: "testjob1"
>
scrape_config: <
job_name: "testjob2"
>
scrape_config: <
job_name: "testjob1"
>

View file

@ -1,57 +0,0 @@
global <
scrape_interval: "30s"
evaluation_interval: "30s"
labels: <
label: <
name: "monitor"
value: "test"
>
>
rule_file: "prometheus.rules"
>
scrape_config: <
job_name: "prometheus"
scrape_interval: "15s"
target_group: <
target: "localhost:9090"
labels: <
label: <
name: "group"
value: "canary"
>
>
>
>
scrape_config: <
job_name: "random"
scrape_interval: "30s"
target_group: <
target: "random.com:8080"
target: "random.com:8081"
target: "random.com:8082"
target: "random.com:8083"
target: "random.com:8084"
labels: <
label: <
name: "group"
value: "production"
>
>
>
target_group: <
target: "random.com:8085"
target: "random.com:8086"
labels: <
label: <
name: "group"
value: "canary"
>
>
>
>

View file

@ -1,8 +0,0 @@
scrape_config: <
job_name: "testjob"
dns_config: <
name: "sd_name"
name: "sd_name2"
refresh_interval: "15s"
>
>

View file

@ -1,406 +0,0 @@
// Code generated by protoc-gen-go.
// source: config.proto
// DO NOT EDIT!
/*
Package io_prometheus is a generated protocol buffer package.
It is generated from these files:
config.proto
It has these top-level messages:
LabelPair
LabelPairs
GlobalConfig
TargetGroup
DNSConfig
RelabelConfig
ScrapeConfig
PrometheusConfig
*/
package io_prometheus
import proto "github.com/golang/protobuf/proto"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = math.Inf
// Action is the action to be performed for the relabeling.
type RelabelConfig_Action int32
const (
RelabelConfig_REPLACE RelabelConfig_Action = 0
RelabelConfig_KEEP RelabelConfig_Action = 1
RelabelConfig_DROP RelabelConfig_Action = 2
)
var RelabelConfig_Action_name = map[int32]string{
0: "REPLACE",
1: "KEEP",
2: "DROP",
}
var RelabelConfig_Action_value = map[string]int32{
"REPLACE": 0,
"KEEP": 1,
"DROP": 2,
}
func (x RelabelConfig_Action) Enum() *RelabelConfig_Action {
p := new(RelabelConfig_Action)
*p = x
return p
}
func (x RelabelConfig_Action) String() string {
return proto.EnumName(RelabelConfig_Action_name, int32(x))
}
func (x *RelabelConfig_Action) UnmarshalJSON(data []byte) error {
value, err := proto.UnmarshalJSONEnum(RelabelConfig_Action_value, data, "RelabelConfig_Action")
if err != nil {
return err
}
*x = RelabelConfig_Action(value)
return nil
}
// A label/value pair suitable for attaching to timeseries.
type LabelPair struct {
// The name of the label. Must adhere to the regex "[a-zA-Z_][a-zA-Z0-9_]*".
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
// The value of the label. May contain any characters.
Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *LabelPair) Reset() { *m = LabelPair{} }
func (m *LabelPair) String() string { return proto.CompactTextString(m) }
func (*LabelPair) ProtoMessage() {}
func (m *LabelPair) GetName() string {
if m != nil && m.Name != nil {
return *m.Name
}
return ""
}
func (m *LabelPair) GetValue() string {
if m != nil && m.Value != nil {
return *m.Value
}
return ""
}
// A set of label/value pairs.
type LabelPairs struct {
Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *LabelPairs) Reset() { *m = LabelPairs{} }
func (m *LabelPairs) String() string { return proto.CompactTextString(m) }
func (*LabelPairs) ProtoMessage() {}
func (m *LabelPairs) GetLabel() []*LabelPair {
if m != nil {
return m.Label
}
return nil
}
// The global Prometheus configuration section.
type GlobalConfig struct {
// How frequently to scrape targets by default. Must be a valid Prometheus
// duration string in the form "[0-9]+[smhdwy]".
ScrapeInterval *string `protobuf:"bytes,1,opt,name=scrape_interval,def=1m" json:"scrape_interval,omitempty"`
// How frequently to evaluate rules by default. Must be a valid Prometheus
// duration string in the form "[0-9]+[smhdwy]".
EvaluationInterval *string `protobuf:"bytes,2,opt,name=evaluation_interval,def=1m" json:"evaluation_interval,omitempty"`
// The labels to add to any timeseries that this Prometheus instance scrapes.
Labels *LabelPairs `protobuf:"bytes,3,opt,name=labels" json:"labels,omitempty"`
// The list of file names of rule files to load.
RuleFile []string `protobuf:"bytes,4,rep,name=rule_file" json:"rule_file,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *GlobalConfig) Reset() { *m = GlobalConfig{} }
func (m *GlobalConfig) String() string { return proto.CompactTextString(m) }
func (*GlobalConfig) ProtoMessage() {}
const Default_GlobalConfig_ScrapeInterval string = "1m"
const Default_GlobalConfig_EvaluationInterval string = "1m"
func (m *GlobalConfig) GetScrapeInterval() string {
if m != nil && m.ScrapeInterval != nil {
return *m.ScrapeInterval
}
return Default_GlobalConfig_ScrapeInterval
}
func (m *GlobalConfig) GetEvaluationInterval() string {
if m != nil && m.EvaluationInterval != nil {
return *m.EvaluationInterval
}
return Default_GlobalConfig_EvaluationInterval
}
func (m *GlobalConfig) GetLabels() *LabelPairs {
if m != nil {
return m.Labels
}
return nil
}
func (m *GlobalConfig) GetRuleFile() []string {
if m != nil {
return m.RuleFile
}
return nil
}
// A labeled group of targets to scrape for a job.
type TargetGroup struct {
// The list of endpoints to scrape via HTTP.
Target []string `protobuf:"bytes,1,rep,name=target" json:"target,omitempty"`
// The labels to add to any timeseries scraped for this target group.
Labels *LabelPairs `protobuf:"bytes,2,opt,name=labels" json:"labels,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *TargetGroup) Reset() { *m = TargetGroup{} }
func (m *TargetGroup) String() string { return proto.CompactTextString(m) }
func (*TargetGroup) ProtoMessage() {}
func (m *TargetGroup) GetTarget() []string {
if m != nil {
return m.Target
}
return nil
}
func (m *TargetGroup) GetLabels() *LabelPairs {
if m != nil {
return m.Labels
}
return nil
}
// The configuration for DNS based service discovery.
type DNSConfig struct {
// The list of DNS-SD service names pointing to SRV records
// containing endpoint information.
Name []string `protobuf:"bytes,1,rep,name=name" json:"name,omitempty"`
// Discovery refresh period when using DNS-SD to discover targets. Must be a
// valid Prometheus duration string in the form "[0-9]+[smhdwy]".
RefreshInterval *string `protobuf:"bytes,2,opt,name=refresh_interval,def=30s" json:"refresh_interval,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *DNSConfig) Reset() { *m = DNSConfig{} }
func (m *DNSConfig) String() string { return proto.CompactTextString(m) }
func (*DNSConfig) ProtoMessage() {}
const Default_DNSConfig_RefreshInterval string = "30s"
func (m *DNSConfig) GetName() []string {
if m != nil {
return m.Name
}
return nil
}
func (m *DNSConfig) GetRefreshInterval() string {
if m != nil && m.RefreshInterval != nil {
return *m.RefreshInterval
}
return Default_DNSConfig_RefreshInterval
}
// The configuration for relabeling of target label sets.
type RelabelConfig struct {
// A list of labels from which values are taken and concatenated
// with the configured separator in order.
SourceLabel []string `protobuf:"bytes,1,rep,name=source_label" json:"source_label,omitempty"`
// Regex against which the concatenation is matched.
Regex *string `protobuf:"bytes,2,req,name=regex" json:"regex,omitempty"`
// The label to which the resulting string is written in a replacement.
TargetLabel *string `protobuf:"bytes,3,opt,name=target_label" json:"target_label,omitempty"`
// Replacement is the regex replacement pattern to be used.
Replacement *string `protobuf:"bytes,4,opt,name=replacement" json:"replacement,omitempty"`
// Separator is the string between concatenated values from the source labels.
Separator *string `protobuf:"bytes,5,opt,name=separator,def=;" json:"separator,omitempty"`
Action *RelabelConfig_Action `protobuf:"varint,6,opt,name=action,enum=io.prometheus.RelabelConfig_Action,def=0" json:"action,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *RelabelConfig) Reset() { *m = RelabelConfig{} }
func (m *RelabelConfig) String() string { return proto.CompactTextString(m) }
func (*RelabelConfig) ProtoMessage() {}
const Default_RelabelConfig_Separator string = ";"
const Default_RelabelConfig_Action RelabelConfig_Action = RelabelConfig_REPLACE
func (m *RelabelConfig) GetSourceLabel() []string {
if m != nil {
return m.SourceLabel
}
return nil
}
func (m *RelabelConfig) GetRegex() string {
if m != nil && m.Regex != nil {
return *m.Regex
}
return ""
}
func (m *RelabelConfig) GetTargetLabel() string {
if m != nil && m.TargetLabel != nil {
return *m.TargetLabel
}
return ""
}
func (m *RelabelConfig) GetReplacement() string {
if m != nil && m.Replacement != nil {
return *m.Replacement
}
return ""
}
func (m *RelabelConfig) GetSeparator() string {
if m != nil && m.Separator != nil {
return *m.Separator
}
return Default_RelabelConfig_Separator
}
func (m *RelabelConfig) GetAction() RelabelConfig_Action {
if m != nil && m.Action != nil {
return *m.Action
}
return Default_RelabelConfig_Action
}
// The configuration for a Prometheus job to scrape.
//
// The next field no. is 11.
type ScrapeConfig struct {
// The job name. Must adhere to the regex "[a-zA-Z_][a-zA-Z0-9_-]*".
JobName *string `protobuf:"bytes,1,req,name=job_name" json:"job_name,omitempty"`
// How frequently to scrape targets from this job. Overrides the global
// default. Must be a valid Prometheus duration string in the form
// "[0-9]+[smhdwy]".
ScrapeInterval *string `protobuf:"bytes,2,opt,name=scrape_interval" json:"scrape_interval,omitempty"`
// Per-target timeout when scraping this job. Must be a valid Prometheus
// duration string in the form "[0-9]+[smhdwy]".
ScrapeTimeout *string `protobuf:"bytes,7,opt,name=scrape_timeout,def=10s" json:"scrape_timeout,omitempty"`
// List of DNS service discovery configurations.
DnsConfig []*DNSConfig `protobuf:"bytes,9,rep,name=dns_config" json:"dns_config,omitempty"`
// List of labeled target groups for this job.
TargetGroup []*TargetGroup `protobuf:"bytes,5,rep,name=target_group" json:"target_group,omitempty"`
// List of relabel configurations.
RelabelConfig []*RelabelConfig `protobuf:"bytes,10,rep,name=relabel_config" json:"relabel_config,omitempty"`
// The HTTP resource path on which to fetch metrics from targets.
MetricsPath *string `protobuf:"bytes,6,opt,name=metrics_path,def=/metrics" json:"metrics_path,omitempty"`
// The URL scheme with which to fetch metrics from targets.
Scheme *string `protobuf:"bytes,8,opt,name=scheme,def=http" json:"scheme,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *ScrapeConfig) Reset() { *m = ScrapeConfig{} }
func (m *ScrapeConfig) String() string { return proto.CompactTextString(m) }
func (*ScrapeConfig) ProtoMessage() {}
const Default_ScrapeConfig_ScrapeTimeout string = "10s"
const Default_ScrapeConfig_MetricsPath string = "/metrics"
const Default_ScrapeConfig_Scheme string = "http"
func (m *ScrapeConfig) GetJobName() string {
if m != nil && m.JobName != nil {
return *m.JobName
}
return ""
}
func (m *ScrapeConfig) GetScrapeInterval() string {
if m != nil && m.ScrapeInterval != nil {
return *m.ScrapeInterval
}
return ""
}
func (m *ScrapeConfig) GetScrapeTimeout() string {
if m != nil && m.ScrapeTimeout != nil {
return *m.ScrapeTimeout
}
return Default_ScrapeConfig_ScrapeTimeout
}
func (m *ScrapeConfig) GetDnsConfig() []*DNSConfig {
if m != nil {
return m.DnsConfig
}
return nil
}
func (m *ScrapeConfig) GetTargetGroup() []*TargetGroup {
if m != nil {
return m.TargetGroup
}
return nil
}
func (m *ScrapeConfig) GetRelabelConfig() []*RelabelConfig {
if m != nil {
return m.RelabelConfig
}
return nil
}
func (m *ScrapeConfig) GetMetricsPath() string {
if m != nil && m.MetricsPath != nil {
return *m.MetricsPath
}
return Default_ScrapeConfig_MetricsPath
}
func (m *ScrapeConfig) GetScheme() string {
if m != nil && m.Scheme != nil {
return *m.Scheme
}
return Default_ScrapeConfig_Scheme
}
// The top-level Prometheus configuration.
type PrometheusConfig struct {
// Global Prometheus configuration options. If omitted, an empty global
// configuration with default values (see GlobalConfig definition) will be
// created.
Global *GlobalConfig `protobuf:"bytes,1,opt,name=global" json:"global,omitempty"`
// The list of scrape configs.
ScrapeConfig []*ScrapeConfig `protobuf:"bytes,3,rep,name=scrape_config" json:"scrape_config,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *PrometheusConfig) Reset() { *m = PrometheusConfig{} }
func (m *PrometheusConfig) String() string { return proto.CompactTextString(m) }
func (*PrometheusConfig) ProtoMessage() {}
func (m *PrometheusConfig) GetGlobal() *GlobalConfig {
if m != nil {
return m.Global
}
return nil
}
func (m *PrometheusConfig) GetScrapeConfig() []*ScrapeConfig {
if m != nil {
return m.ScrapeConfig
}
return nil
}
func init() {
proto.RegisterEnum("io.prometheus.RelabelConfig_Action", RelabelConfig_Action_name, RelabelConfig_Action_value)
}

View file

@ -1,53 +0,0 @@
// Copyright 2013 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.
package config
import (
"io/ioutil"
"github.com/golang/protobuf/proto"
pb "github.com/prometheus/prometheus/config/generated"
)
// LoadFromString returns a config parsed from the provided string.
func LoadFromString(configStr string) (*Config, error) {
configProto := pb.PrometheusConfig{}
if err := proto.UnmarshalText(configStr, &configProto); err != nil {
return nil, err
}
if configProto.Global == nil {
configProto.Global = &pb.GlobalConfig{}
}
for _, scfg := range configProto.GetScrapeConfig() {
if scfg.ScrapeInterval == nil {
scfg.ScrapeInterval = proto.String(configProto.Global.GetScrapeInterval())
}
}
config := &Config{configProto}
err := config.Validate()
return config, err
}
// LoadFromFile returns a config parsed from the file of the provided name.
func LoadFromFile(fileName string) (*Config, error) {
configStr, err := ioutil.ReadFile(fileName)
if err != nil {
return nil, err
}
return LoadFromString(string(configStr))
}

View file

@ -1,25 +0,0 @@
// Copyright 2013 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.
package config
import (
"testing"
)
func TestLoadFromFile(t *testing.T) {
_, err := LoadFromFile("file-does-not-exist.conf")
if err == nil {
t.Error("Error expected on non-existing config file path but got none")
}
}

61
config/testdata/conf.good.yml vendored Normal file
View file

@ -0,0 +1,61 @@
# my global config
global_config:
scrape_interval: 15s
evaluation_interval: 30s
# scrape_timeout is set to the global default (10s).
labels:
monitor: codelab
foo: bar
rule_files:
- "first.rules"
- "second.rules"
scrape_configs:
- job_name: prometheus
# scrape_interval is defined by the configured global (15s).
# scrape_timeout is defined by the global default (10s).
# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
labels:
foo: baz
target_groups:
- targets: ['localhost:9090', 'localhost:9191']
labels:
my: label
your: label
relabel_configs:
- source_labels: [job, __meta_dns_srv_name]
regex: (.*)some-[regex]$
target_label: job
replacement: foo-${1}
# action defaults to 'replace'
- job_name: service-x
scrape_interval: 50s
scrape_timeout: 5s
metrics_path: /my_path
# scheme defaults to 'http'.
dns_configs:
- refresh_interval: 15s
names:
- first.dns.address.domain.com
- second.dns.address.domain.com
- names:
- first.dns.address.domain.com
# refresh_interval defaults to 30s.
relabel_configs:
- source_labels: [job]
regex: (.*)some-[regex]$
action: drop

2
config/testdata/jobname.bad.yml vendored Normal file
View file

@ -0,0 +1,2 @@
scrape_configs:
- job_name: prom^etheus

5
config/testdata/jobname_dup.bad.yml vendored Normal file
View file

@ -0,0 +1,5 @@
# Two scrape configs with the same job names are not allowed.
scrape_configs:
- job_name: prometheus
- job_name: service-x
- job_name: prometheus

3
config/testdata/labelname.bad.yml vendored Normal file
View file

@ -0,0 +1,3 @@
global_config:
labels:
not$allowed: value

4
config/testdata/regex.bad.yml vendored Normal file
View file

@ -0,0 +1,4 @@
scrape_configs:
- job_name: prometheus
relabel_configs:
- regex: abc(def

View file

@ -161,7 +161,7 @@ func NewPrometheus() *prometheus {
ruleManager := manager.NewRuleManager(&manager.RuleManagerOptions{
SampleAppender: sampleAppender,
NotificationHandler: notificationHandler,
EvaluationInterval: conf.EvaluationInterval(),
EvaluationInterval: time.Duration(conf.GlobalConfig.EvaluationInterval),
Storage: memStorage,
PrometheusURL: web.MustBuildServerURL(*pathPrefix),
PathPrefix: *pathPrefix,

View file

@ -1,13 +1,12 @@
package retrieval
import (
"regexp"
"fmt"
"strings"
clientmodel "github.com/prometheus/client_golang/model"
"github.com/prometheus/prometheus/config"
pb "github.com/prometheus/prometheus/config/generated"
)
// Relabel returns a relabeled copy of the given label set. The relabel configurations
@ -31,40 +30,34 @@ func Relabel(labels clientmodel.LabelSet, cfgs ...*config.RelabelConfig) (client
}
func relabel(labels clientmodel.LabelSet, cfg *config.RelabelConfig) (clientmodel.LabelSet, error) {
pat, err := regexp.Compile(cfg.GetRegex())
if err != nil {
return nil, err
values := make([]string, 0, len(cfg.SourceLabels))
for _, ln := range cfg.SourceLabels {
values = append(values, string(labels[ln]))
}
val := strings.Join(values, cfg.Separator)
values := make([]string, 0, len(cfg.GetSourceLabel()))
for _, name := range cfg.GetSourceLabel() {
values = append(values, string(labels[clientmodel.LabelName(name)]))
}
val := strings.Join(values, cfg.GetSeparator())
switch cfg.GetAction() {
case pb.RelabelConfig_DROP:
if pat.MatchString(val) {
switch cfg.Action {
case config.RelabelDrop:
if cfg.Regex.MatchString(val) {
return nil, nil
}
case pb.RelabelConfig_KEEP:
if !pat.MatchString(val) {
case config.RelabelKeep:
if !cfg.Regex.MatchString(val) {
return nil, nil
}
case pb.RelabelConfig_REPLACE:
case config.RelabelReplace:
// If there is no match no replacement must take place.
if !pat.MatchString(val) {
if !cfg.Regex.MatchString(val) {
break
}
res := pat.ReplaceAllString(val, cfg.GetReplacement())
ln := clientmodel.LabelName(cfg.GetTargetLabel())
res := cfg.Regex.ReplaceAllString(val, cfg.Replacement)
if res == "" {
delete(labels, ln)
delete(labels, cfg.TargetLabel)
} else {
labels[ln] = clientmodel.LabelValue(res)
labels[cfg.TargetLabel] = clientmodel.LabelValue(res)
}
default:
panic("retrieval.relabel: unknown relabel action type")
panic(fmt.Errorf("retrieval.relabel: unknown relabel action type %q", cfg.Action))
}
return labels, nil
}

View file

@ -2,20 +2,18 @@ package retrieval
import (
"reflect"
"regexp"
"testing"
"github.com/golang/protobuf/proto"
clientmodel "github.com/prometheus/client_golang/model"
"github.com/prometheus/prometheus/config"
pb "github.com/prometheus/prometheus/config/generated"
)
func TestRelabel(t *testing.T) {
tests := []struct {
input clientmodel.LabelSet
relabel []pb.RelabelConfig
relabel []config.DefaultedRelabelConfig
output clientmodel.LabelSet
}{
{
@ -24,14 +22,14 @@ func TestRelabel(t *testing.T) {
"b": "bar",
"c": "baz",
},
relabel: []pb.RelabelConfig{
relabel: []config.DefaultedRelabelConfig{
{
SourceLabel: []string{"a"},
Regex: proto.String("f(.*)"),
TargetLabel: proto.String("d"),
Separator: proto.String(";"),
Replacement: proto.String("ch${1}-ch${1}"),
Action: pb.RelabelConfig_REPLACE.Enum(),
SourceLabels: clientmodel.LabelNames{"a"},
Regex: &config.Regexp{*regexp.MustCompile("f(.*)")},
TargetLabel: clientmodel.LabelName("d"),
Separator: ";",
Replacement: "ch${1}-ch${1}",
Action: config.RelabelReplace,
},
},
output: clientmodel.LabelSet{
@ -47,21 +45,22 @@ func TestRelabel(t *testing.T) {
"b": "bar",
"c": "baz",
},
relabel: []pb.RelabelConfig{
relabel: []config.DefaultedRelabelConfig{
{
SourceLabel: []string{"a", "b"},
Regex: proto.String("^f(.*);(.*)r$"),
TargetLabel: proto.String("a"),
Separator: proto.String(";"),
Replacement: proto.String("b${1}${2}m"), // boobam
SourceLabels: clientmodel.LabelNames{"a", "b"},
Regex: &config.Regexp{*regexp.MustCompile("^f(.*);(.*)r$")},
TargetLabel: clientmodel.LabelName("a"),
Separator: ";",
Replacement: "b${1}${2}m", // boobam
Action: config.RelabelReplace,
},
{
SourceLabel: []string{"c", "a"},
Regex: proto.String("(b).*b(.*)ba(.*)"),
TargetLabel: proto.String("d"),
Separator: proto.String(";"),
Replacement: proto.String("$1$2$2$3"),
Action: pb.RelabelConfig_REPLACE.Enum(),
SourceLabels: clientmodel.LabelNames{"c", "a"},
Regex: &config.Regexp{*regexp.MustCompile("(b).*b(.*)ba(.*)")},
TargetLabel: clientmodel.LabelName("d"),
Separator: ";",
Replacement: "$1$2$2$3",
Action: config.RelabelReplace,
},
},
output: clientmodel.LabelSet{
@ -75,18 +74,18 @@ func TestRelabel(t *testing.T) {
input: clientmodel.LabelSet{
"a": "foo",
},
relabel: []pb.RelabelConfig{
relabel: []config.DefaultedRelabelConfig{
{
SourceLabel: []string{"a"},
Regex: proto.String("o$"),
Action: pb.RelabelConfig_DROP.Enum(),
SourceLabels: clientmodel.LabelNames{"a"},
Regex: &config.Regexp{*regexp.MustCompile("o$")},
Action: config.RelabelDrop,
}, {
SourceLabel: []string{"a"},
Regex: proto.String("f(.*)"),
TargetLabel: proto.String("d"),
Separator: proto.String(";"),
Replacement: proto.String("ch$1-ch$1"),
Action: pb.RelabelConfig_REPLACE.Enum(),
SourceLabels: clientmodel.LabelNames{"a"},
Regex: &config.Regexp{*regexp.MustCompile("f(.*)")},
TargetLabel: clientmodel.LabelName("d"),
Separator: ";",
Replacement: "ch$1-ch$1",
Action: config.RelabelReplace,
},
},
output: nil,
@ -95,11 +94,11 @@ func TestRelabel(t *testing.T) {
input: clientmodel.LabelSet{
"a": "foo",
},
relabel: []pb.RelabelConfig{
relabel: []config.DefaultedRelabelConfig{
{
SourceLabel: []string{"a"},
Regex: proto.String("no-match"),
Action: pb.RelabelConfig_DROP.Enum(),
SourceLabels: clientmodel.LabelNames{"a"},
Regex: &config.Regexp{*regexp.MustCompile("no-match")},
Action: config.RelabelDrop,
},
},
output: clientmodel.LabelSet{
@ -110,11 +109,11 @@ func TestRelabel(t *testing.T) {
input: clientmodel.LabelSet{
"a": "foo",
},
relabel: []pb.RelabelConfig{
relabel: []config.DefaultedRelabelConfig{
{
SourceLabel: []string{"a"},
Regex: proto.String("no-match"),
Action: pb.RelabelConfig_KEEP.Enum(),
SourceLabels: clientmodel.LabelNames{"a"},
Regex: &config.Regexp{*regexp.MustCompile("no-match")},
Action: config.RelabelKeep,
},
},
output: nil,
@ -123,11 +122,11 @@ func TestRelabel(t *testing.T) {
input: clientmodel.LabelSet{
"a": "foo",
},
relabel: []pb.RelabelConfig{
relabel: []config.DefaultedRelabelConfig{
{
SourceLabel: []string{"a"},
Regex: proto.String("^f"),
Action: pb.RelabelConfig_KEEP.Enum(),
SourceLabels: clientmodel.LabelNames{"a"},
Regex: &config.Regexp{*regexp.MustCompile("^f")},
Action: config.RelabelKeep,
},
},
output: clientmodel.LabelSet{
@ -139,13 +138,13 @@ func TestRelabel(t *testing.T) {
input: clientmodel.LabelSet{
"a": "boo",
},
relabel: []pb.RelabelConfig{
relabel: []config.DefaultedRelabelConfig{
{
SourceLabel: []string{"a"},
Regex: proto.String("^f"),
Action: pb.RelabelConfig_REPLACE.Enum(),
TargetLabel: proto.String("b"),
Replacement: proto.String("bar"),
SourceLabels: clientmodel.LabelNames{"a"},
Regex: &config.Regexp{*regexp.MustCompile("^f")},
TargetLabel: clientmodel.LabelName("b"),
Replacement: "bar",
Action: config.RelabelReplace,
},
},
output: clientmodel.LabelSet{
@ -157,7 +156,6 @@ func TestRelabel(t *testing.T) {
for i, test := range tests {
var relabel []*config.RelabelConfig
for _, rl := range test.relabel {
proto.SetDefaults(&rl)
relabel = append(relabel, &config.RelabelConfig{rl})
}
res, err := Relabel(test.input, relabel...)

View file

@ -190,12 +190,12 @@ func (t *target) Update(cfg *config.ScrapeConfig, baseLabels clientmodel.LabelSe
t.Lock()
defer t.Unlock()
t.url.Scheme = cfg.GetScheme()
t.url.Scheme = cfg.Scheme
t.url.Path = string(baseLabels[clientmodel.MetricsPathLabel])
t.scrapeInterval = cfg.ScrapeInterval()
t.deadline = cfg.ScrapeTimeout()
t.httpClient = utility.NewDeadlineClient(cfg.ScrapeTimeout())
t.scrapeInterval = time.Duration(cfg.ScrapeInterval)
t.deadline = time.Duration(cfg.ScrapeTimeout)
t.httpClient = utility.NewDeadlineClient(time.Duration(cfg.ScrapeTimeout))
t.baseLabels = clientmodel.LabelSet{}
// All remaining internal labels will not be part of the label set.

View file

@ -26,8 +26,6 @@ import (
clientmodel "github.com/prometheus/client_golang/model"
"github.com/golang/protobuf/proto"
"github.com/prometheus/prometheus/config"
"github.com/prometheus/prometheus/utility"
)
@ -91,9 +89,6 @@ func TestTargetScrapeWithFullChannel(t *testing.T) {
}
func TestTargetRecordScrapeHealth(t *testing.T) {
scfg := &config.ScrapeConfig{}
proto.SetDefaults(&scfg.ScrapeConfig)
testTarget := newTestTarget("example.url", 0, clientmodel.LabelSet{clientmodel.JobLabel: "testjob"})
now := clientmodel.Now()
@ -150,9 +145,6 @@ func TestTargetScrapeTimeout(t *testing.T) {
)
defer server.Close()
scfg := &config.ScrapeConfig{}
proto.SetDefaults(&scfg.ScrapeConfig)
var testTarget Target = newTestTarget(server.URL, 10*time.Millisecond, clientmodel.LabelSet{})
appender := nopAppender{}

View file

@ -17,13 +17,13 @@ import (
"fmt"
"strings"
"sync"
"time"
"github.com/golang/glog"
clientmodel "github.com/prometheus/client_golang/model"
"github.com/prometheus/prometheus/config"
pb "github.com/prometheus/prometheus/config/generated"
"github.com/prometheus/prometheus/retrieval/discovery"
"github.com/prometheus/prometheus/storage"
)
@ -124,7 +124,7 @@ func (tm *TargetManager) handleTargetUpdates(cfg *config.ScrapeConfig, ch <-chan
// Thus, oscilliating label sets for targets with the same source,
// but providers from different configs, are prevented.
func fullSource(cfg *config.ScrapeConfig, src string) string {
return cfg.GetJobName() + ":" + src
return cfg.JobName + ":" + src
}
// Stop all background processing.
@ -289,7 +289,7 @@ func (tm *TargetManager) applyConfig(cfg *config.Config) error {
// Only apply changes if everything was successful.
providers := map[*config.ScrapeConfig][]TargetProvider{}
for _, scfg := range cfg.ScrapeConfigs() {
for _, scfg := range cfg.ScrapeConfigs {
provs, err := ProvidersFromConfig(scfg)
if err != nil {
return err
@ -299,7 +299,7 @@ func (tm *TargetManager) applyConfig(cfg *config.Config) error {
tm.m.Lock()
defer tm.m.Unlock()
tm.globalLabels = cfg.GlobalLabels()
tm.globalLabels = cfg.GlobalConfig.Labels
tm.providers = providers
return nil
}
@ -315,7 +315,10 @@ func (tm *TargetManager) targetsFromGroup(tg *config.TargetGroup, cfg *config.Sc
// set already. Apply the labelsets in order of decreasing precedence.
labelsets := []clientmodel.LabelSet{
tg.Labels,
cfg.Labels(),
clientmodel.LabelSet{
clientmodel.MetricsPathLabel: clientmodel.LabelValue(cfg.MetricsPath),
clientmodel.JobLabel: clientmodel.LabelValue(cfg.JobName),
},
tm.globalLabels,
}
for _, lset := range labelsets {
@ -330,7 +333,7 @@ func (tm *TargetManager) targetsFromGroup(tg *config.TargetGroup, cfg *config.Sc
return nil, fmt.Errorf("instance %d in target group %s has no address", i, tg)
}
labels, err := Relabel(labels, cfg.RelabelConfigs()...)
labels, err := Relabel(labels, cfg.RelabelConfigs...)
if err != nil {
return nil, fmt.Errorf("error while relabelling instance %d in target group %s: %s", i, tg, err)
}
@ -357,13 +360,12 @@ func (tm *TargetManager) targetsFromGroup(tg *config.TargetGroup, cfg *config.Sc
func ProvidersFromConfig(cfg *config.ScrapeConfig) ([]TargetProvider, error) {
var providers []TargetProvider
for _, dnscfg := range cfg.DNSConfigs() {
dnsSD := discovery.NewDNSDiscovery(dnscfg.GetName(), dnscfg.RefreshInterval())
for _, dnscfg := range cfg.DNSConfigs {
dnsSD := discovery.NewDNSDiscovery(dnscfg.Names, time.Duration(dnscfg.RefreshInterval))
providers = append(providers, dnsSD)
}
if tgs := cfg.GetTargetGroup(); tgs != nil {
static := NewStaticProvider(tgs)
providers = append(providers, static)
if len(cfg.TargetGroups) > 0 {
providers = append(providers, NewStaticProvider(cfg.TargetGroups))
}
return providers, nil
}
@ -375,25 +377,13 @@ type StaticProvider struct {
// NewStaticProvider returns a StaticProvider configured with the given
// target groups.
func NewStaticProvider(groups []*pb.TargetGroup) *StaticProvider {
prov := &StaticProvider{}
func NewStaticProvider(groups []*config.TargetGroup) *StaticProvider {
for i, tg := range groups {
g := &config.TargetGroup{
Source: fmt.Sprintf("static:%d", i),
Labels: clientmodel.LabelSet{},
tg.Source = fmt.Sprintf("static:%d", i)
}
for _, pair := range tg.GetLabels().GetLabel() {
g.Labels[clientmodel.LabelName(pair.GetName())] = clientmodel.LabelValue(pair.GetValue())
return &StaticProvider{
TargetGroups: groups,
}
for _, t := range tg.GetTarget() {
g.Targets = append(g.Targets, clientmodel.LabelSet{
clientmodel.AddressLabel: clientmodel.LabelValue(t),
})
}
prov.TargetGroups = append(prov.TargetGroups, g)
}
return prov
}
// Run implements the TargetProvider interface.

View file

@ -15,25 +15,26 @@ package retrieval
import (
"reflect"
"regexp"
"testing"
"time"
"github.com/golang/protobuf/proto"
clientmodel "github.com/prometheus/client_golang/model"
"github.com/prometheus/prometheus/config"
pb "github.com/prometheus/prometheus/config/generated"
)
func TestTargetManagerChan(t *testing.T) {
testJob1 := &config.ScrapeConfig{pb.ScrapeConfig{
JobName: proto.String("test_job1"),
ScrapeInterval: proto.String("1m"),
TargetGroup: []*pb.TargetGroup{
{Target: []string{"example.org:80", "example.com:80"}},
testJob1 := &config.ScrapeConfig{config.DefaultedScrapeConfig{
JobName: "test_job1",
ScrapeInterval: config.Duration(1 * time.Minute),
TargetGroups: []*config.TargetGroup{{
Targets: []clientmodel.LabelSet{
{clientmodel.AddressLabel: "example.org:80"},
{clientmodel.AddressLabel: "example.com:80"},
},
}},
}
}}
prov1 := &fakeTargetProvider{
sources: []string{"src1", "src2"},
update: make(chan *config.TargetGroup),
@ -153,63 +154,76 @@ func TestTargetManagerChan(t *testing.T) {
}
func TestTargetManagerConfigUpdate(t *testing.T) {
testJob1 := &pb.ScrapeConfig{
JobName: proto.String("test_job1"),
ScrapeInterval: proto.String("1m"),
TargetGroup: []*pb.TargetGroup{
{Target: []string{"example.org:80", "example.com:80"}},
testJob1 := &config.ScrapeConfig{config.DefaultedScrapeConfig{
JobName: "test_job1",
ScrapeInterval: config.Duration(1 * time.Minute),
TargetGroups: []*config.TargetGroup{{
Targets: []clientmodel.LabelSet{
{clientmodel.AddressLabel: "example.org:80"},
{clientmodel.AddressLabel: "example.com:80"},
},
}
testJob2 := &pb.ScrapeConfig{
JobName: proto.String("test_job2"),
ScrapeInterval: proto.String("1m"),
TargetGroup: []*pb.TargetGroup{
{
Target: []string{"example.org:8080", "example.com:8081"},
Labels: &pb.LabelPairs{Label: []*pb.LabelPair{
{Name: proto.String("foo"), Value: proto.String("bar")},
{Name: proto.String("boom"), Value: proto.String("box")},
}},
},
{Target: []string{"test.com:1234"}},
}}
testJob2 := &config.ScrapeConfig{config.DefaultedScrapeConfig{
JobName: "test_job2",
ScrapeInterval: config.Duration(1 * time.Minute),
TargetGroups: []*config.TargetGroup{
{
Target: []string{"test.com:1235"},
Labels: &pb.LabelPairs{Label: []*pb.LabelPair{
{Name: proto.String("instance"), Value: proto.String("fixed")},
Targets: []clientmodel.LabelSet{
{clientmodel.AddressLabel: "example.org:8080"},
{clientmodel.AddressLabel: "example.com:8081"},
},
Labels: clientmodel.LabelSet{
"foo": "bar",
"boom": "box",
},
},
{
Targets: []clientmodel.LabelSet{
{clientmodel.AddressLabel: "test.com:1234"},
},
},
{
Targets: []clientmodel.LabelSet{
{clientmodel.AddressLabel: "test.com:1235"},
},
Labels: clientmodel.LabelSet{"instance": "fixed"},
},
},
RelabelConfigs: []*config.RelabelConfig{
{config.DefaultedRelabelConfig{
SourceLabels: clientmodel.LabelNames{clientmodel.AddressLabel},
Regex: &config.Regexp{*regexp.MustCompile(`^test\.(.*?):(.*)`)},
Replacement: "foo.${1}:${2}",
TargetLabel: clientmodel.AddressLabel,
Action: config.RelabelReplace,
}},
},
},
RelabelConfig: []*pb.RelabelConfig{
{
SourceLabel: []string{string(clientmodel.AddressLabel)},
Regex: proto.String(`^test\.(.*?):(.*)`),
Replacement: proto.String("foo.${1}:${2}"),
TargetLabel: proto.String(string(clientmodel.AddressLabel)),
}, {
{config.DefaultedRelabelConfig{
// Add a new label for example.* targets.
SourceLabel: []string{string(clientmodel.AddressLabel), "boom", "foo"},
Regex: proto.String("^example.*?-b([a-z-]+)r$"),
TargetLabel: proto.String("new"),
Replacement: proto.String("$1"),
Separator: proto.String("-"),
}, {
SourceLabels: clientmodel.LabelNames{clientmodel.AddressLabel, "boom", "foo"},
Regex: &config.Regexp{*regexp.MustCompile("^example.*?-b([a-z-]+)r$")},
TargetLabel: "new",
Replacement: "$1",
Separator: "-",
Action: config.RelabelReplace,
}},
{config.DefaultedRelabelConfig{
// Drop an existing label.
SourceLabel: []string{"boom"},
Regex: proto.String(".*"),
TargetLabel: proto.String("boom"),
Replacement: proto.String(""),
SourceLabels: clientmodel.LabelNames{"boom"},
Regex: &config.Regexp{*regexp.MustCompile(".*")},
TargetLabel: "boom",
Replacement: "",
Action: config.RelabelReplace,
}},
},
},
}
proto.SetDefaults(testJob1)
proto.SetDefaults(testJob2)
}}
sequence := []struct {
scrapeConfigs []*pb.ScrapeConfig
scrapeConfigs []*config.ScrapeConfig
expected map[string][]clientmodel.LabelSet
}{
{
scrapeConfigs: []*pb.ScrapeConfig{testJob1},
scrapeConfigs: []*config.ScrapeConfig{testJob1},
expected: map[string][]clientmodel.LabelSet{
"test_job1:static:0": {
{clientmodel.JobLabel: "test_job1", clientmodel.InstanceLabel: "example.org:80"},
@ -217,7 +231,7 @@ func TestTargetManagerConfigUpdate(t *testing.T) {
},
},
}, {
scrapeConfigs: []*pb.ScrapeConfig{testJob1},
scrapeConfigs: []*config.ScrapeConfig{testJob1},
expected: map[string][]clientmodel.LabelSet{
"test_job1:static:0": {
{clientmodel.JobLabel: "test_job1", clientmodel.InstanceLabel: "example.org:80"},
@ -225,7 +239,7 @@ func TestTargetManagerConfigUpdate(t *testing.T) {
},
},
}, {
scrapeConfigs: []*pb.ScrapeConfig{testJob1, testJob2},
scrapeConfigs: []*config.ScrapeConfig{testJob1, testJob2},
expected: map[string][]clientmodel.LabelSet{
"test_job1:static:0": {
{clientmodel.JobLabel: "test_job1", clientmodel.InstanceLabel: "example.org:80"},
@ -243,10 +257,10 @@ func TestTargetManagerConfigUpdate(t *testing.T) {
},
},
}, {
scrapeConfigs: []*pb.ScrapeConfig{},
scrapeConfigs: []*config.ScrapeConfig{},
expected: map[string][]clientmodel.LabelSet{},
}, {
scrapeConfigs: []*pb.ScrapeConfig{testJob2},
scrapeConfigs: []*config.ScrapeConfig{testJob2},
expected: map[string][]clientmodel.LabelSet{
"test_job2:static:0": {
{clientmodel.JobLabel: "test_job2", clientmodel.InstanceLabel: "example.org:8080", "foo": "bar", "new": "ox-ba"},
@ -261,8 +275,9 @@ func TestTargetManagerConfigUpdate(t *testing.T) {
},
},
}
conf := &config.Config{DefaultedConfig: config.DefaultConfig}
targetManager, err := NewTargetManager(&config.Config{}, nopAppender{})
targetManager, err := NewTargetManager(conf, nopAppender{})
if err != nil {
t.Fatal(err)
}
@ -270,10 +285,8 @@ func TestTargetManagerConfigUpdate(t *testing.T) {
defer targetManager.Stop()
for i, step := range sequence {
cfg := pb.PrometheusConfig{
ScrapeConfig: step.scrapeConfigs,
}
err := targetManager.ApplyConfig(&config.Config{cfg})
conf.ScrapeConfigs = step.scrapeConfigs
err := targetManager.ApplyConfig(conf)
if err != nil {
t.Fatal(err)
}

View file

@ -268,7 +268,7 @@ func (m *ruleManager) runIteration() {
}
func (m *ruleManager) AddRulesFromConfig(config *config.Config) error {
for _, ruleFile := range config.Global.RuleFile {
for _, ruleFile := range config.RuleFiles {
newRules, err := rules.LoadRulesFromFile(ruleFile)
if err != nil {
return fmt.Errorf("%s: %s", ruleFile, err)