VictoriaMetrics/lib/promscrape/discovery/dockerswarm/nodes.go
Aliaksandr Valialkin be6da5053f
lib/promscrape: optimize service discovery speed
- Return meta-labels for the discovered targets via promutils.Labels
  instead of map[string]string. This improves the speed of generating
  meta-labels for discovered targets by up to 5x.

- Remove memory allocations in hot paths during ScrapeWork generation.
  The ScrapeWork contains scrape settings for a single discovered target.
  This improves the service discovery speed by up to 2x.
2022-11-29 21:26:23 -08:00

89 lines
2.5 KiB
Go

package dockerswarm
import (
"encoding/json"
"fmt"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
)
// See https://docs.docker.com/engine/api/v1.40/#tag/Node
type node struct {
ID string
Spec struct {
Labels map[string]string
Role string
Availability string
}
Description struct {
Hostname string
Platform struct {
Architecture string
OS string
}
Engine struct {
EngineVersion string
}
}
Status struct {
State string
Message string
Addr string
}
ManagerStatus struct {
Leader bool
Reachability string
Addr string
}
}
func getNodesLabels(cfg *apiConfig) ([]*promutils.Labels, error) {
nodes, err := getNodes(cfg)
if err != nil {
return nil, err
}
return addNodeLabels(nodes, cfg.port), nil
}
func getNodes(cfg *apiConfig) ([]node, error) {
resp, err := cfg.getAPIResponse("/nodes")
if err != nil {
return nil, fmt.Errorf("cannot query dockerswarm api for nodes: %w", err)
}
return parseNodes(resp)
}
func parseNodes(data []byte) ([]node, error) {
var nodes []node
if err := json.Unmarshal(data, &nodes); err != nil {
return nil, fmt.Errorf("cannot parse nodes: %w", err)
}
return nodes, nil
}
func addNodeLabels(nodes []node, port int) []*promutils.Labels {
var ms []*promutils.Labels
for _, node := range nodes {
m := promutils.NewLabels(16)
m.Add("__address__", discoveryutils.JoinHostPort(node.Status.Addr, port))
m.Add("__meta_dockerswarm_node_address", node.Status.Addr)
m.Add("__meta_dockerswarm_node_availability", node.Spec.Availability)
m.Add("__meta_dockerswarm_node_engine_version", node.Description.Engine.EngineVersion)
m.Add("__meta_dockerswarm_node_hostname", node.Description.Hostname)
m.Add("__meta_dockerswarm_node_id", node.ID)
m.Add("__meta_dockerswarm_node_manager_address", node.ManagerStatus.Addr)
m.Add("__meta_dockerswarm_node_manager_leader", fmt.Sprintf("%t", node.ManagerStatus.Leader))
m.Add("__meta_dockerswarm_node_manager_reachability", node.ManagerStatus.Reachability)
m.Add("__meta_dockerswarm_node_platform_architecture", node.Description.Platform.Architecture)
m.Add("__meta_dockerswarm_node_platform_os", node.Description.Platform.OS)
m.Add("__meta_dockerswarm_node_role", node.Spec.Role)
m.Add("__meta_dockerswarm_node_status", node.Status.State)
for k, v := range node.Spec.Labels {
m.Add(discoveryutils.SanitizeLabelName("__meta_dockerswarm_node_label_"+k), v)
}
ms = append(ms, m)
}
return ms
}