-
Notifications
You must be signed in to change notification settings - Fork 336
feat: elasticsearch_up 指标添加cluster标签 #1413
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f6bab8e
d540942
0518f97
7f12bb3
8472cd5
b4df3fc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -197,7 +197,7 @@ type Nodes struct { | |
| } | ||
|
|
||
| // NewNodes defines Nodes Prometheus metrics | ||
| func NewNodes(client *http.Client, url *url.URL, all bool, node string, local bool, nodeStats []string) *Nodes { | ||
| func NewNodes(client *http.Client, url *url.URL, all bool, node string, local bool, nodeStats []string, clusterName string) *Nodes { | ||
| return &Nodes{ | ||
| client: client, | ||
| url: url, | ||
|
|
@@ -209,14 +209,26 @@ func NewNodes(client *http.Client, url *url.URL, all bool, node string, local bo | |
| up: prometheus.NewGauge(prometheus.GaugeOpts{ | ||
| Name: prometheus.BuildFQName(namespace, "node_stats", "up"), | ||
| Help: "Was the last scrape of the Elasticsearch nodes endpoint successful.", | ||
| ConstLabels: prometheus.Labels{ | ||
| "cluster": clusterName, | ||
| "address": url.String(), | ||
| }, | ||
| }), | ||
| totalScrapes: prometheus.NewCounter(prometheus.CounterOpts{ | ||
| Name: prometheus.BuildFQName(namespace, "node_stats", "total_scrapes"), | ||
| Help: "Current total Elasticsearch node scrapes.", | ||
| ConstLabels: prometheus.Labels{ | ||
| "cluster": clusterName, | ||
| "address": url.String(), | ||
| }, | ||
| }), | ||
| jsonParseFailures: prometheus.NewCounter(prometheus.CounterOpts{ | ||
| Name: prometheus.BuildFQName(namespace, "node_stats", "json_parse_failures"), | ||
| Help: "Number of errors while parsing JSON.", | ||
| ConstLabels: prometheus.Labels{ | ||
| "cluster": clusterName, | ||
| "address": url.String(), | ||
| }, | ||
| }), | ||
|
|
||
| transportMetrics: []*nodeMetric{ | ||
|
|
@@ -2275,6 +2287,39 @@ func GetNodeID(client *http.Client, user, password, s string) (string, error) { | |
| return "", nil | ||
| } | ||
|
|
||
| func GetClusterName(client *http.Client, user, password, s string) (string, error) { | ||
| u, err := url.Parse(s) | ||
| if err != nil { | ||
| return "", fmt.Errorf("failed to parse URL %s: %s", s, err) | ||
| } | ||
| if user != "" && password != "" { | ||
| u.User = url.UserPassword(user, password) | ||
| } | ||
|
|
||
| var cir ClusterInfoResponse | ||
| res, err := client.Get(u.String()) | ||
| if err != nil { | ||
| return "", fmt.Errorf("failed to get cluster info from %s: %s", u.String(), err) | ||
| } | ||
|
Comment on lines
+2290
to
+2303
|
||
| defer func() { | ||
| err = res.Body.Close() | ||
| if err != nil { | ||
| log.Println("failed to close response body, err: ", err) | ||
| } | ||
| }() | ||
| if res.StatusCode != http.StatusOK { | ||
| return "", fmt.Errorf("HTTP Request failed with code %d", res.StatusCode) | ||
| } | ||
| bts, err := io.ReadAll(res.Body) | ||
| if err != nil { | ||
| return "", err | ||
| } | ||
| if err := json.Unmarshal(bts, &cir); err != nil { | ||
| return "", err | ||
| } | ||
| return cir.ClusterName, nil | ||
| } | ||
|
Comment on lines
+2290
to
+2321
|
||
|
|
||
| func GetCatMaster(client *http.Client, user, password, s string) (string, error) { | ||
| u, err := url.Parse(s) | ||
| if err != nil { | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -96,8 +96,9 @@ type ( | |||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| serverInfo struct { | ||||||||||||||
| nodeID string | ||||||||||||||
| masterID string | ||||||||||||||
| nodeID string | ||||||||||||||
| masterID string | ||||||||||||||
| clusterName string | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| IndicesInfo struct { | ||||||||||||||
|
|
@@ -204,7 +205,16 @@ func (ins *Instance) Gather(slist *types.SampleList) { | |||||||||||||
| return | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| slist.PushSample("elasticsearch", "up", 1, map[string]string{"address": s}) | ||||||||||||||
| if info.clusterName, err = collector.GetClusterName(ins.Client, ins.UserName, ins.Password, s); err != nil { | ||||||||||||||
| slist.PushSample("elasticsearch", "up", 0, map[string]string{"address": s}) | ||||||||||||||
| log.Println("E! failed to get cluster name:", err) | ||||||||||||||
| return | ||||||||||||||
| } | ||||||||||||||
|
Comment on lines
+208
to
+212
|
||||||||||||||
|
|
||||||||||||||
| slist.PushSample("elasticsearch", "up", 1, map[string]string{ | ||||||||||||||
| "address": s, | ||||||||||||||
| "cluster": info.clusterName, | ||||||||||||||
| }) | ||||||||||||||
kongfei605 marked this conversation as resolved.
Show resolved
Hide resolved
Comment on lines
+208
to
+217
|
||||||||||||||
| ins.serverInfoMutex.Lock() | ||||||||||||||
| ins.serverInfo[s] = info | ||||||||||||||
| ins.serverInfoMutex.Unlock() | ||||||||||||||
|
|
@@ -272,7 +282,7 @@ func (ins *Instance) Gather(slist *types.SampleList) { | |||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // Always gather node stats | ||||||||||||||
| if err := inputs.Collect(collector.NewNodes(ins.Client, EsUrl, ins.AllNodes, ins.Node, ins.Local, ins.NodeStats), slist); err != nil { | ||||||||||||||
| if err := inputs.Collect(collector.NewNodes(ins.Client, EsUrl, ins.AllNodes, ins.Node, ins.Local, ins.NodeStats, ins.serverInfo[ins.Node].clusterName), slist); err != nil { | ||||||||||||||
|
||||||||||||||
| if err := inputs.Collect(collector.NewNodes(ins.Client, EsUrl, ins.AllNodes, ins.Node, ins.Local, ins.NodeStats, ins.serverInfo[ins.Node].clusterName), slist); err != nil { | |
| clusterName := "" | |
| if info, ok := ins.serverInfo[s]; ok { | |
| clusterName = info.clusterName | |
| } | |
| if err := inputs.Collect(collector.NewNodes(ins.Client, EsUrl, ins.AllNodes, ins.Node, ins.Local, ins.NodeStats, clusterName), slist); err != nil { |
Copilot
AI
Mar 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NewNodes(..., ins.serverInfo[ins.Node].clusterName) looks up serverInfo using ins.Node (e.g. "_local"), but serverInfo is populated with keys of the server URL string (s). This will typically pass an empty cluster name. Also, ins.serverInfo is only refreshed inside the earlier if ins.ClusterStats || len(ins.IndicesInclude) > 0 block; when that block is skipped, this read can use stale data from a previous run. Please derive the cluster name for the current server (s / EsUrl) with consistent key normalization and ensure it’s populated (or explicitly empty) on every Gather run before passing into NewNodes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NewNodessetsaddressConstLabels tourl.String(). Since the URL passed in is configured with basic auth (EsUrl.User = url.UserPassword(...)), this will embed credentials (user/password or API key) into Prometheus labels/metrics output. Please ensure the address label is derived from a sanitized URL (e.g., clone the URL and clearUser, or useScheme+Hostonly) so secrets are never exported as labels.