lib/promscrape/discovery/dockerswarm: fix discovery filters being applied to all objects (#3632)

* lib/promscrape/discovery/dockerswarm: fix discovery filters being applied to all objects

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>

* Update docs/CHANGELOG.md

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com>
This commit is contained in:
Zakhar Bessarab 2023-01-12 10:50:34 +04:00 committed by Aliaksandr Valialkin
parent fc28543e30
commit 0b2f6d0d89
No known key found for this signature in database
GPG key ID: A72BEC6CD3D0DED1
7 changed files with 35 additions and 9 deletions

View file

@ -15,6 +15,7 @@ The following tip changes can be tested by building VictoriaMetrics components f
## v1.79.x long-time support release (LTS) ## v1.79.x long-time support release (LTS)
* BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): [dockerswarm_sd_configs](https://docs.victoriametrics.com/sd_configs.html#dockerswarm_sd_configs): apply `filters` only to objects of the specified `role`. Previously filters were applied to all the objects, which could cause errors when different types of objects were used with filters that were not compatible with them. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3579).
* BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): suppress all the scrape errors when `-promscrape.suppressScrapeErrors` is enabled. Previously some scrape errors were logged even if `-promscrape.suppressScrapeErrors` flag was set. * BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): suppress all the scrape errors when `-promscrape.suppressScrapeErrors` is enabled. Previously some scrape errors were logged even if `-promscrape.suppressScrapeErrors` flag was set.
* BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): consistently put the scrape url with scrape target labels to all error logs for failed scrapes. Previously some failed scrapes were logged without this information. * BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): consistently put the scrape url with scrape target labels to all error logs for failed scrapes. Previously some failed scrapes were logged without this information.
* BUGFIX: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): properly parse `M` and `Mi` suffixes as `1e6` multipliers in `1M` and `1Mi` numeric constants. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3664). The issue has been introduced in [v1.79.7](https://docs.victoriametrics.com/CHANGELOG.html#v1797). * BUGFIX: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): properly parse `M` and `Mi` suffixes as `1e6` multipliers in `1M` and `1Mi` numeric constants. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3664). The issue has been introduced in [v1.79.7](https://docs.victoriametrics.com/CHANGELOG.html#v1797).

View file

@ -16,6 +16,9 @@ type apiConfig struct {
client *discoveryutils.Client client *discoveryutils.Client
port int port int
// role is the type of objects to discover.
role string
// filtersQueryArg contains escaped `filters` query arg to add to each request to Docker Swarm API. // filtersQueryArg contains escaped `filters` query arg to add to each request to Docker Swarm API.
filtersQueryArg string filtersQueryArg string
} }
@ -49,11 +52,12 @@ func newAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
return nil, fmt.Errorf("cannot create HTTP client for %q: %w", sdc.Host, err) return nil, fmt.Errorf("cannot create HTTP client for %q: %w", sdc.Host, err)
} }
cfg.client = client cfg.client = client
cfg.role = sdc.Role
return cfg, nil return cfg, nil
} }
func (cfg *apiConfig) getAPIResponse(path string) ([]byte, error) { func (cfg *apiConfig) getAPIResponse(path, filtersQueryArg string) ([]byte, error) {
if len(cfg.filtersQueryArg) > 0 { if len(filtersQueryArg) > 0 {
separator := "?" separator := "?"
if strings.Contains(path, "?") { if strings.Contains(path, "?") {
separator = "&" separator = "&"

View file

@ -14,6 +14,12 @@ var SDCheckInterval = flag.Duration("promscrape.dockerswarmSDCheckInterval", 30*
"This works only if dockerswarm_sd_configs is configured in '-promscrape.config' file. "+ "This works only if dockerswarm_sd_configs is configured in '-promscrape.config' file. "+
"See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#dockerswarm_sd_config for details") "See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#dockerswarm_sd_config for details")
const (
roleTasks = "tasks"
roleServices = "services"
roleNodes = "nodes"
)
// SDConfig represents docker swarm service discovery configuration // SDConfig represents docker swarm service discovery configuration
// //
// See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#dockerswarm_sd_config // See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#dockerswarm_sd_config
@ -42,11 +48,11 @@ func (sdc *SDConfig) GetLabels(baseDir string) ([]map[string]string, error) {
return nil, fmt.Errorf("cannot get API config: %w", err) return nil, fmt.Errorf("cannot get API config: %w", err)
} }
switch sdc.Role { switch sdc.Role {
case "tasks": case roleTasks:
return getTasksLabels(cfg) return getTasksLabels(cfg)
case "services": case roleServices:
return getServicesLabels(cfg) return getServicesLabels(cfg)
case "nodes": case roleNodes:
return getNodesLabels(cfg) return getNodesLabels(cfg)
default: default:
return nil, fmt.Errorf("unexpected `role`: %q; must be one of `tasks`, `services` or `nodes`; skipping it", sdc.Role) return nil, fmt.Errorf("unexpected `role`: %q; must be one of `tasks`, `services` or `nodes`; skipping it", sdc.Role)

View file

@ -27,7 +27,7 @@ func getNetworksLabelsByNetworkID(cfg *apiConfig) (map[string]map[string]string,
} }
func getNetworks(cfg *apiConfig) ([]network, error) { func getNetworks(cfg *apiConfig) ([]network, error) {
resp, err := cfg.getAPIResponse("/networks") resp, err := cfg.getAPIResponse("/networks", "")
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot query dockerswarm api for networks: %w", err) return nil, fmt.Errorf("cannot query dockerswarm api for networks: %w", err)
} }

View file

@ -46,7 +46,12 @@ func getNodesLabels(cfg *apiConfig) ([]map[string]string, error) {
} }
func getNodes(cfg *apiConfig) ([]node, error) { func getNodes(cfg *apiConfig) ([]node, error) {
resp, err := cfg.getAPIResponse("/nodes") filtersQueryArg := ""
if cfg.role == roleNodes {
filtersQueryArg = cfg.filtersQueryArg
}
resp, err := cfg.getAPIResponse("/nodes", filtersQueryArg)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot query dockerswarm api for nodes: %w", err) return nil, fmt.Errorf("cannot query dockerswarm api for nodes: %w", err)
} }

View file

@ -59,7 +59,12 @@ func getServicesLabels(cfg *apiConfig) ([]map[string]string, error) {
} }
func getServices(cfg *apiConfig) ([]service, error) { func getServices(cfg *apiConfig) ([]service, error) {
data, err := cfg.getAPIResponse("/services") filtersQueryArg := ""
if cfg.role == roleServices {
filtersQueryArg = cfg.filtersQueryArg
}
data, err := cfg.getAPIResponse("/services", filtersQueryArg)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot query dockerswarm api for services: %w", err) return nil, fmt.Errorf("cannot query dockerswarm api for services: %w", err)
} }

View file

@ -61,7 +61,12 @@ func getTasksLabels(cfg *apiConfig) ([]map[string]string, error) {
} }
func getTasks(cfg *apiConfig) ([]task, error) { func getTasks(cfg *apiConfig) ([]task, error) {
resp, err := cfg.getAPIResponse("/tasks") filtersQueryArg := ""
if cfg.role == roleTasks {
filtersQueryArg = cfg.filtersQueryArg
}
resp, err := cfg.getAPIResponse("/tasks", filtersQueryArg)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot query dockerswarm api for tasks: %w", err) return nil, fmt.Errorf("cannot query dockerswarm api for tasks: %w", err)
} }